You are viewing a plain text version of this content. The canonical link for it is here.
Posted to gitbox@activemq.apache.org by GitBox <gi...@apache.org> on 2021/02/25 10:14:11 UTC

[GitHub] [activemq-artemis] laeubi opened a new pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

laeubi opened a new pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470


   This adds Support for [ARTEMIS-3106](https://issues.apache.org/jira/browse/ARTEMIS-3106) and adds the following parts:
   
   - An implementation for SASL-SCRAM-SHA1/256/512 based on [SCRAM SASL authentication for Java](https://github.com/ogrebgr/scram-sasl)
   - A properties based SASL-SCRAM LoginModule to manage user and roles
   - A LoginModule using the acquired credentials from the SASL-SCRAM Module to perform the login in Artemis
   - An example Server/Client that demonstrates the use


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785923418


   This is a great contribution :-) I will need to peek in more detail but for a start you verify that the license/notices on the files that are not your own match what is required https://www.apache.org/legal/src-headers.html#3party


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597036899



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       Adding unit tests for the code of the very functionality you are adding is clearly not 'out of scope'.
   
   I've also already pointed you at some unit tests for this very same broker behaviour that you are adding, which could easily be used 'for inspiration'. 
   
   You are also using a client here in your systest that has it, and which that the library you have 'taken inspiration from' actually lifted its own client impl from to begin with.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596996437



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       @gemmellr as mentioned before kerberos (and SASL-SCRAM) uses a special authentication realm to do the transport-layer authentication.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785987366


   > I have spitted this PR in 5 commits:
   > 
   > 1. Code developed completely by my own with the standard headers added
   > 2. Code I have taken from  https://github.com/ogrebgr/scram-sasl modified it (e.g. additional exception checks, removed unnecessary parts), that code is originally licensed APL 2.0 and I have keep the original headers there
   > 3. I reformated my code and the 3rd-party code according to the Artemis checkstyle rules
   > 4. An example that uses both codes, inspired by the artemis examples
   > 5. some refactoring that was necessary for handling users+roles
   > 
   > I hope this makes clear whats "my" work and what might be "derived" or "prio" work, as everything is/was Apache licensed I'm not sure if/how notice files need to be addressed here.
   
   It's probably ok... but I think you should state original authorship on the classes where you're deriving it.
   
   
   for the specific derivation I think you should keep it a separate commit for what's worth.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600354223



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/Normalizer.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2011 Glenn Maynard
+ * <p>
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Dynamically-loaded interface for java.text.Normalizer(NFKC); it's missing in non-bleeding-edge
+ * versions of Android and we can get by without it.
+ */
+@SuppressWarnings({ "SpellCheckingInspection", "JavaDoc" })
+class Normalizer {

Review comment:
       is this class really necessary? 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r585566420



##########
File path: NOTICE
##########
@@ -3,3 +3,8 @@ Copyright [2014-2021] The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the ScramServerFunctionality.java, ScramServerFunctionalityImpl.java,
+ScramException.java,  ScramUtils.java, UserData.java
+is "SCRAM SASL authentication for Java" (https://github.com/ogrebgr/scram-sasl)
+Copyright 2016 Ognyan Bankov, Licensed under the Apache License, Version 2.0

Review comment:
       Sorry I don't understand hwo this relates to qpid-broker-j ?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597037998



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       You can have users (e.g. old client) that only support SHA-1 and could generate "legacy entries" for them, while having some never clients use SHA-256 (think about a migration from SHA1- to SHA-256 where not all clients can upgrade) and still advertise support for both mechanism. The client has to choose the mechanism. Also JAAS allows a delegation strategy where several providers are asked in a row and such, so I don't think enforcing/limiting the server is suitable here.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816656898


   @laeubi The SaslScramTest added is failing 100% of the time.
   
   Do you know how to fix it?
   
   I have sent a refactoring to use ActiveMQTestBase but it was failing before... (My change has nothing to do with the failure).
   
   
   I should have done a full test suite before merging this... I had done one some time ago and I did not see this failure for some reason back then. Can you check it please?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-788662593


   I have added now:
   
   - Integration Test
   - info to notice file
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r591107311



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SHA512CRAMServerSASLFactory.java
##########
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+
+/**
+ * provides SASL SCRAM-SHA512
+ */
+public class SHA512CRAMServerSASLFactory extends SCRAMServerSASLFactory {

Review comment:
       I'll drop SHA512 completely for now




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599295293



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       Is there any example in Artemis using AMQP+SASL (plain) for inter broker communication I could use to check this case?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816691886


   @laeubi  I wanted to verify the example, but I am at a loss. mvn verify does very little! and there is no detail in the readme. Is there something missing?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597049903



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       Can the file have both types at the same time for a given user? Seems like it cant if its properties based?
   
   Perhaps have separate providers for each mech as I suggested, with their own file, let people who want to have a delegation strategy configure it as such?
   
   Clients should really be unaware of whether the server has their credentials only in SCRAM-SHA-1 or in SCRAM-SHA256 format etc if both mechs are being offered. If a mech is offered its meant to work if the client supports it. Someone with old clients only capable of SCRAM-SHA1 (do you know of any such AMQP 1.0 clients?) if offered, should be able to update their client and simply use the SCRAM-SHA256 if it was offered, and just expect that to work. Thats kind of the point of negotiating what is supported.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816673679


   I think @gtully  is right, simply remove all lines that test for SCRAM-SHA-1 should work, also remove SCRAM-SHA-1 from the examples offered mechanism.
   https://github.com/apache/activemq-artemis/pull/3470/files#diff-c5cb9c0a6b3ecdcff45874a643969f237ed8b1a119e790b0ad4b109bb82317d8R69
   
   and following ...


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600733110



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));

Review comment:
       at this point it is unknown if it is an encoded one or an unencoded one. I can exchange this but it does not matters much.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-788902105


   I think the JDK14 failure is just an existing problem test that sporadically fails. The Travis CI JDK8 build is on the other hand failing for issues with the example (its probably time we had the GitHub Actions build do the same additional check that build is doing).


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r585575202



##########
File path: NOTICE
##########
@@ -3,3 +3,8 @@ Copyright [2014-2021] The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the ScramServerFunctionality.java, ScramServerFunctionalityImpl.java,
+ScramException.java,  ScramUtils.java, UserData.java
+is "SCRAM SASL authentication for Java" (https://github.com/ogrebgr/scram-sasl)
+Copyright 2016 Ognyan Bankov, Licensed under the Apache License, Version 2.0

Review comment:
       In a previous comment I pointed to some tests for the SCRAM impl in qpid-broker-j. I was saying I would personally lift from that impl instead if people thought we actually need to adjust the notice file here. Though as I said, I dont think editing the file is needed.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-1012221646


   @Neustradamus SHA256 + SHA512 where implemented as far as I remmber, can you explain whats the issue? The whole implementation is rather flexible and it should be possible to enhance or adjust it quite easy feel free to suggest a PR :-)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: gitbox-unsubscribe@activemq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597087489



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       I dont think that would make sense, so that would be back to seeming sensible to only have each module do one mech point for me.
   
   At the very least, I think the example demonstrates a configuration people shouldnt ever really use it in (plus also having the plain text), so for me its not a great example in that regard. Its obviously reasonable the test covers the plaintext storage variant if its going to be allowed.
   
   Clients shouldnt need apriori knowledge of what mechs the server is storing their details for in general. That would somewhat defeat the reason for SASL being there. Yes, you might need their input in order to introduce a new SCRAM mech support if only storing non-plaintext, thats not quite the same thing.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597047369



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       For me adding a sasl-client implementation in the context that there is no AMQP-Client I'm aware of that support SHA-512 (yet) is at least too much hassle. The cupid client do not support SHA-512 and the "client" from the SASL-SCRAM-Lib only supports the authentication but not AMQP...




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596983961



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       Could be if it ever let them do anything before it turns out they cant actually log in? Or as you said above, if there are other modules..do they maybe not get called in cases they should?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599522161



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       >>For me adding a sasl-client implementation in the context that there is no AMQP-Client I'm aware of that support SHA-512 (yet) is at least too much hassle.
   
   My earlier comments about unit tests were about all the supported mechs, the point on the SHA-512 specifically was just that it would have then actually had some tests and could have remained (since the tests would after all be rather common, differing in the algorithm used and some expected values, i.e a likely trivial amount of additional effort). 
   
   > Artemis includes a JMS client but I can't find how it is used, is there an example that uses AMQP+SASL+Artemis JMS Client?
   
   There are vast numbers of examples (see the examples dir) and tests showing how the Artemis JMS client can be used, so I assume its something more nuanced you are asking? I'd note though that Artemis JMS client uses Artemis' own Core protocol, which doesnt support SASL.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] tabish121 commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
tabish121 commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806838558


   Agree with @gtully and @gemmellr on the drop of SCRAM-SHA-1.  Think we should go forward only with 256 and 512 at this point.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806836053


   I think we should scrap the SCRAM-SHA-1 support, we are late to the party, so lets go straight to 256


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599564401



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       okay I think it makes sense then to delay SHA-512 support until theres actually a AMQP client supporting it. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] Neustradamus commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
Neustradamus commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-1013625688


   @laeubi: Thanks for your details :)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: gitbox-unsubscribe@activemq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-1013623826


   You can see the implementations here:
   https://github.com/apache/activemq-artemis/tree/main/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram
   
   so it is SHA256+SHA512. Support for SHA1 was dropped. If you have a strong use-case for SHA1 you should open a new ticket describing it, its really not that hard to add other mechanisms.
   
   Effectively you have to to do these things;
   
   1. Add a new SCRAM method [here](https://github.com/apache/activemq-artemis/blob/main/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java)
   2. Add a new Factory (see [here for an example](https://github.com/apache/activemq-artemis/blob/main/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SHA512SCRAMServerSASLFactory.java))
   3. Add it it in the [list of mechanisms](https://github.com/apache/activemq-artemis/blob/main/artemis-protocols/artemis-amqp-protocol/src/main/resources/META-INF/services/org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory) so it could be discovered.
   
   I even did this once for the md5 set of hash functions for demonstration purpose so you are not limited ti SHA-X at all...


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: gitbox-unsubscribe@activemq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601444802



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/AMQPConnectSaslTest.java
##########
@@ -151,6 +164,34 @@ public void testConnectsWithPlain() throws Exception {
       assertArrayEquals(expectedPlainInitialResponse(USER, PASSWD), authenticator.getInitialResponse());
    }
 
+   @Test(timeout = 200000)
+   public void testConnectsWithSCRAM() throws Exception {
+      CountDownLatch serverConnectionOpen = new CountDownLatch(1);
+      SCRAMTestAuthenticator authenticator = new SCRAMTestAuthenticator(SCRAM.SHA512);

Review comment:
       I realise that, it is part of my point. Since it is the only mechanism offered by the server, then the connecting broker clearly had to pick that mechanism (or fail if it doesnt support it at all). Offering other mechs (as many of the other tests in the class do) then also verifies the actual selection behaviour, i.e that it will prefer selecting SCRAM 512 when it is offered, rather than only doing so because it had no other choice. That way if someone accidentally breaks that logic later the test can at least point it out.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601440355



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         userData = generateUserData(password);
+      }
+      return true;
+   }
+
+   private UserData generateUserData(String plainTextPassword) throws LoginException {
+      if (plainTextPassword == null) {
+         // if the user is not available (or the password) generate a random password here so an
+         // attacker can't
+         // distinguish between a missing username and a wrong password
+         byte[] randomPassword = new byte[256];
+         RANDOM_GENERATOR.nextBytes(randomPassword);
+         plainTextPassword = new String(randomPassword);
+      }
+      DigestCallback digestCallback = new DigestCallback();
+      HmacCallback hmacCallback = new HmacCallback();
+      executeCallbacks(digestCallback, hmacCallback);
+      byte[] salt = generateSalt();
+      try {
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(plainTextPassword, salt, 4096,
+                                                                          digestCallback.getDigest(),
+                                                                          hmacCallback.getHmac()));
+         return new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+      } catch (ScramException e) {
+         throw new LoginException();
+      }
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[32];
+      RANDOM_GENERATOR.nextBytes(salt);
+      return salt;
+   }
+
+   private void executeCallbacks(Callback... callbacks) throws LoginException {
+      try {
+         callbackHandler.handle(callbacks);
+      } catch (UnsupportedCallbackException | IOException e) {
+         throw new LoginException();
+      }
+   }
+
+   @Override
+   public boolean commit() throws LoginException {
+      if (userData == null) {
+         throw new LoginException();
+      }
+      subject.getPublicCredentials().add(userData);
+      Set<UserPrincipal> authenticatedUsers = subject.getPrincipals(UserPrincipal.class);
+      UserPrincipal principal = new UserPrincipal(user);
+      principals.add(principal);
+      authenticatedUsers.add(principal);
+      for (UserPrincipal userPrincipal : authenticatedUsers) {
+         Set<String> matchedRoles = roles.get(userPrincipal.getName());
+         if (matchedRoles != null) {
+            for (String entry : matchedRoles) {
+               principals.add(new RolePrincipal(entry));
+            }
+         }
+      }
+      subject.getPrincipals().addAll(principals);
+      return true;
+   }
+
+   @Override
+   public boolean abort() throws LoginException {
+      return true;
+   }
+
+   @Override
+   public boolean logout() throws LoginException {
+      subject.getPrincipals().removeAll(principals);
+      principals.clear();
+      subject.getPublicCredentials().remove(userData);
+      userData = null;
+      return true;
+   }
+
+   /**
+    * Main method that could be used to encrypt given credentials for use in properties files
+    * @param args username password type [iterations]
+    * @throws GeneralSecurityException if any security mechanism is not available on this JVM
+    * @throws ScramException if invalid data is supplied
+    */
+   public static void main(String[] args) throws GeneralSecurityException, ScramException {
+      if (args.length < 2) {
+         System.out.println("Usage: " + SCRAMPropertiesLoginModule.class.getSimpleName() +
+                  " <username> <password> [<iterations>]");
+         System.out.println("\ttype: " + getSupportedTypes());
+         System.out.println("\titerations desired number of iteration (min value: " + MIN_ITERATIONS + ")");
+         return;
+      }
+      String username = args[0];
+      String password = args[1];
+      for (SCRAM scram : SCRAM.values()) {
+         MessageDigest digest = MessageDigest.getInstance(scram.getDigest());
+         Mac hmac = Mac.getInstance(scram.getHmac());
+         byte[] salt = generateSalt();
+         int iterations;
+         if (args.length > 2) {
+            iterations = Integer.parseInt(args[2]);
+            if (iterations < MIN_ITERATIONS) {
+               throw new IllegalArgumentException("minimum of " + MIN_ITERATIONS + " required!");
+            }
+         } else {
+            iterations = MIN_ITERATIONS;
+         }
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, iterations, digest, hmac));
+         System.out.println(username + SEPARATOR_MECHANISM + scram.name() + " = " +

Review comment:
       Then I would probably rip out the untested client side stuff allowing for them and simplify it personally. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816666919


   @clebertsuconic I thought the test was executed on the PR in the buildserver before? Is there a link to the failing build so I can take a look at it?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r603152750



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep.StringPrepError;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      if (user == null) {
+         userData = generateUserData(null); // generate random user data
+      } else {
+         String password = users.getProperty(user + SEPARATOR_MECHANISM + scram.name());
+         if (password == null) {
+            // fallback for probably unencoded user/password or a single encoded entry
+            password = users.getProperty(user);
+         }
+         if (PasswordMaskingUtil.isEncMasked(password)) {
+            String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);

Review comment:
       Sorry I don't understand this here. if the properties file is messed then we are out of luck and this needs to be fixed, the implementation is not a debugging util. I also don't get what this has to do with user registration?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816695783


   ok,thanks. all the rest do the mvn verify route... i will see to add the necessary bits such that these can follow the current templates


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-809230968


   @tabish121 I have seen you have added SHA512 support to QPID is there any plan for a release in the near future?I probably could then add the test case for the client side too.
   
   I could remove SHA1 if it help to move this forward but don't see any real benefit from it, if one likes to use it why not? And as even the spec mention it as a minimum requirement it will just decrease interoperability.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816670236


   it looks like it verifies SHA-1 but there is no mechanism for that, which is ok, there should not be.
   what is odd is that the broker is configured to expose it as a mechanism but there is no validation. I guess we could improve that.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] Neustradamus commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
Neustradamus commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-1012030551


   @laeubi and others: Thanks for your improvement about SCRAM!
   
   Why do you support only SCRAM-SHA-256?
   
   But I see:
   - https://github.com/apache/activemq-artemis/search?q=scram-sha-1
   - https://github.com/apache/activemq-artemis/search?q=scram-sha-512
   
   Note: There were improvements here:
   - https://github.com/ogrebgr/scram-sasl
   
   Linked to:
   - https://github.com/scram-xmpp/info/issues/1


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: gitbox-unsubscribe@activemq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596963183



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       hmm. sort of answering my own question... login will then be a blocking call depending on the sasl exchanges needing an executor etc. my be more trouble that it is worth.
   I guess the real question is: it there any harm in the early successful login?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597056430



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       Theoretical that would be possible if one would save the mechanism used to encrypt the data as well e.g. something like:
   
   username:SHA1=...
   username:SHA256=....
   
   I'm just not sure if we should complicate things to much here. If users have complex/advanced deployment demands it might be better to fire off an own LoginModule that is not based on plain properties files.
   
   No one is forced to configure the server to offer more than one mechanism though, if one likes to he should know about the consequences. The scheme is part of the SASL-SCRAM initial setup phase there is no way to "upgrade" older credentials on the server side, so the used mechanism is part of the apriori knowledge of the client as well as his username and password.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814126306


   @gtully can we squash before merged?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806051272


   > My earlier feedback about lack of unit tests remains.
   is there anything specifically you are missing here? The integration test should already cover most of the use-cases I think.
   
   > I really would consider just omitting the SCRAM-SHA-1 support at this point personally, I dont see great value in adding it at this 
   But whats the value in removing it? It does not simplify the code, it is not enabled by default (so peopel can choose if they want to enable it or not) and it does not remove complexity as it is just another set of algorithms. On the other hand, adding it "later" or let people "just plug in their own support for it" seems way much more effort on the long run. For example the client-side is currently not pluggable.
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr edited a comment on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr edited a comment on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785986384


   > can you squash all commits up to now.. it would be easier to review it.
   
   While I'd certainly squash things at the end, I dont think it make much difference for review if its squashed. Its combined in the UI, and you can view things combined locally with git diff, or get github to generate the combined patch (e.g https://github.com/apache/activemq-artemis/pull/3470.patch)


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785986384


   > can you squash all commits up to now.. it would be easier to review it.
   
   While I'd certainly squash things at the end, I dont think it make much difference for review if its squashed. Its combined in the UI, and you can view things combined locally with git diff, or get github to generate the combined patch (e.g https://patch-diff.githubusercontent.com/raw/apache/activemq-artemis/pull/3470.patch)


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601426481



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;

Review comment:
       I guess this works for now if really needed, as it shouldnt actually occur...but seems more than a bit ugly, and could certainly mislead if it occurs, given there isnt actually any proton based decoding happening at the time its thrown.
   
   This isnt a protcol error as such, but an auth process failure. Something specific should be handling such failures specifically in Artemis, and presumably isnt currently, and in such cases the socket should then just need to be killed as there is actually no protocol route for the client side to report a SASL failure, only servers.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600726761



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();

Review comment:
       username is mandatory and should normally always be available so this is just a "fake" key must not collide with any username. I don't see any advantage in having it null compared to a synthetic one.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814298961


   try:
   
   mvn javadoc:javadoc
   
   with jdk 8
   
   unfortunately the CI is not currently checking for javadocs... I tried to add the javadoc check on the CI build and I couldn't figure out at the time, got busy and never got to do it...
   
   But the failures are real..
   
   you think you could fix them? if not let me know and I will figure out.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785966319


   I'd expect to see testing for auth code like this, especially unit tests but likely an actual systest also. It doesnt seem like there is any (though obviously there is an example, so somewhat counts if it were run)
   
   Perhaps some unit testing inspiration could be taken from [another broker](https://github.com/apache/qpid-broker-j/blob/8.0.4/broker-core/src/test/java/org/apache/qpid/server/security/auth/sasl/scram/ScramNegotiatorTest.java). Its impl might also have allowed for direct lifting without any licensing and attribution consideration at all, already being licensed to the foundation.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600359216



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/Normalizer.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2011 Glenn Maynard
+ * <p>
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Dynamically-loaded interface for java.text.Normalizer(NFKC); it's missing in non-bleeding-edge
+ * versions of Android and we can get by without it.
+ */
+@SuppressWarnings({ "SpellCheckingInspection", "JavaDoc" })
+class Normalizer {

Review comment:
       I replaced this with default java, I think we don't need to care about old android here...




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785988040


   > I just had some difficulties getting the embedded server running with qpid on the classpath due to dependencies conflicts so I spited them in two part in the example but will try to investigate how this could be combined into one combined itest.
   
   Take a look into smoke-tests... you can create a real server... it's pretty much the example framework where you create a real server, but with unit-tests.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599553511



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       The Artemis JMS client does not use AMQP, no. It uses the Artemis 'Core' protocol, which does not support SASL.
   
   The Qpid JMS client uses AMQP 1.0, which does support SASL. It works with Artemis (and others) since it supports multiple protocols including AMQP 1.0.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600725299



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;

Review comment:
       That's the only way o report an error on the protocol level i found so far




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599553511



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       The Artemis JMS client does not use AMQP, no. It uses the Artemis 'Core' protocol, which does not support SASL.
   
   The Qpid JMS client uses AMQP 1.0, which does support SASL. It works with Artemis (and others) since the broker supports multiple protocols including AMQP 1.0.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r603151559



##########
File path: artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/SCRAMTest.java
##########
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.crypto.Mac;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.SCRAMClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.SCRAMServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramServerFunctionalityImpl;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.hamcrest.core.IsInstanceOf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * test cases for the SASL-SCRAM
+ */
+@RunWith(Parameterized.class)
+public class SCRAMTest {
+
+   /**
+    *
+    */
+   private final SCRAM mechanism;
+   private static final byte[] SALT = new byte[32];
+   private static final String SNONCE = "server";
+   private static final String CNONCE = "client";
+   private static final String USERNAME = "test";
+   private static final String PASSWORD = "123";
+
+   @Parameters(name = "{0}")
+   public static List<Object[]> data() {
+      List<Object[]> list = new ArrayList<>();
+      for (SCRAM scram : SCRAM.values()) {
+         list.add(new Object[] {scram});
+      }
+      return list;
+   }
+
+   public SCRAMTest(SCRAM mechanism) {
+      this.mechanism = mechanism;
+   }
+
+   @Test
+   public void testSuccess() throws NoSuchAlgorithmException {
+      TestSCRAMServerSASL serverSASL = new TestSCRAMServerSASL(mechanism, USERNAME, PASSWORD);
+      TestSCRAMClientSASL clientSASL = new TestSCRAMClientSASL(mechanism, USERNAME, PASSWORD);

Review comment:
       > Wiring them in a circle like this doesnt really verify the behaviour is truly as expected
   it at least verifies that the client+server side could work together. combined with the QPID test it verifies that other implementations behave similar.
   
   > it uses the example straight from the RFC to check the actual behaviour based on known input.
   I could add those as well but this also jut test one fixed set of data. So even if my test-string are not "visible" in code they always use the same string.
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-813896235


   > I'm going to leave further review here for some of the main broker maintainers.
   
   Can you add relevant maintainers here so we can further proceed?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596991120



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       If the SCRAM-SHA-512 support was removed it would seem this and various related bits below should go also.
   
   (Personally I'd have left it and added some actual unit tests)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597000952



##########
File path: examples/protocols/amqp/sasl-scram/pom.xml
##########
@@ -0,0 +1,40 @@
+<?xml version='1.0'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.activemq.examples.amqp</groupId>
+        <artifactId>amqp</artifactId>
+        <version>2.18.0-SNAPSHOT</version>
+    </parent>
+

Review comment:
       you need the properties section:
       <properties>
           <activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
       </properties>
   
   that is what is borking checkstype with the -Prelease jdk8 build. Then it barfs on lots of check style tab v spaces in the example code




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601532122



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep.StringPrepError;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      if (user == null) {
+         userData = generateUserData(null); // generate random user data
+      } else {
+         String password = users.getProperty(user + SEPARATOR_MECHANISM + scram.name());
+         if (password == null) {
+            // fallback for probably unencoded user/password or a single encoded entry
+            password = users.getProperty(user);
+         }
+         if (PasswordMaskingUtil.isEncMasked(password)) {
+            String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);

Review comment:
       I think we can defer cli support, the main provides a usable mechanism to register users. There may be a need to have some sort of plugable user registration thing for the cli, but that can be explored in the future




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] Neustradamus commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
Neustradamus commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-1013622141


   @laeubi: Sorry, the title is not perfect ^^
   SHA-1 + SHA-256 + SHA-512 or SHA-256 + SHA-512?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: gitbox-unsubscribe@activemq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601498584



##########
File path: artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/SCRAMTest.java
##########
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.crypto.Mac;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.SCRAMClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.SCRAMServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramServerFunctionalityImpl;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.hamcrest.core.IsInstanceOf;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * test cases for the SASL-SCRAM
+ */
+@RunWith(Parameterized.class)
+public class SCRAMTest {
+
+   /**
+    *
+    */
+   private final SCRAM mechanism;
+   private static final byte[] SALT = new byte[32];
+   private static final String SNONCE = "server";
+   private static final String CNONCE = "client";
+   private static final String USERNAME = "test";
+   private static final String PASSWORD = "123";
+
+   @Parameters(name = "{0}")
+   public static List<Object[]> data() {
+      List<Object[]> list = new ArrayList<>();
+      for (SCRAM scram : SCRAM.values()) {
+         list.add(new Object[] {scram});
+      }
+      return list;
+   }
+
+   public SCRAMTest(SCRAM mechanism) {
+      this.mechanism = mechanism;
+   }
+
+   @Test
+   public void testSuccess() throws NoSuchAlgorithmException {
+      TestSCRAMServerSASL serverSASL = new TestSCRAMServerSASL(mechanism, USERNAME, PASSWORD);
+      TestSCRAMClientSASL clientSASL = new TestSCRAMClientSASL(mechanism, USERNAME, PASSWORD);

Review comment:
       So this type of test indeed will rarely give a different result than the integration test, since its using mostly the same code doing the same thing, I can see why you would wonder about having both with this test in particular. 
   
   Wiring them in a circle like this doesnt really verify the behaviour is truly as expected, so much as that neither side blew up. I'd expect each side to be tested in isolation with some actual verification of its generated output.
   
   E.g for the client side, https://github.com/apache/qpid-jms/tree/main/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl contains example of the kind of client handling tests I would expect. At least for the SHA1 and 256 cases for example, it uses the example straight from the RFC to check the actual behaviour based on known input.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600584160



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;

Review comment:
       Seems unusual to be throwing Proton's decode exception here.

##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;
+
+/**
+ * implements the client part of SASL-SCRAM for broker interconnect
+ */
+public class SCRAMClientSASL implements ClientSASL {
+   private final SCRAM scramType;
+   private final ScramClientFunctionalityImpl client;
+   private final String username;
+   private final String password;
+
+   /**
+    * @param scram the SCRAM mechanism to use
+    * @param username the username for authentication
+    * @param password the password for authentication
+    */
+   public SCRAMClientSASL(SCRAM scram, String username, String password) {
+      Objects.requireNonNull(scram);
+      Objects.requireNonNull(username);
+      Objects.requireNonNull(password);
+      this.username = username;
+      this.password = password;
+      this.scramType = scram;
+      client = new ScramClientFunctionalityImpl(scram.getDigest(), scram.getHmac(), UUID.randomUUID().toString());
+   }
+
+   @Override
+   public String getName() {
+      return scramType.getName();
+   }
+
+   @Override
+   public byte[] getInitialResponse() {
+      try {
+         String firstMessage = client.prepareFirstMessage(username);
+         System.out.println("SCRAMClientSASL.getInitialResponse() >> " + firstMessage);
+         return firstMessage.getBytes(StandardCharsets.US_ASCII);
+      } catch (ScramException e) {
+         throw new DecodeException("prepareFirstMessage failed", e);
+      }
+   }
+
+   @Override
+   public byte[] getResponse(byte[] challenge) {
+      String msg = new String(challenge, StandardCharsets.US_ASCII);
+      System.out.println("SCRAMClientSASL.getResponse() << " + msg);

Review comment:
       Leftover System.out.println

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();

Review comment:
       Do we need to generate a fake username, cant it just be left null and the rest handle that?

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         userData = generateUserData(password);
+      }
+      return true;
+   }
+
+   private UserData generateUserData(String plainTextPassword) throws LoginException {
+      if (plainTextPassword == null) {
+         // if the user is not available (or the password) generate a random password here so an
+         // attacker can't
+         // distinguish between a missing username and a wrong password
+         byte[] randomPassword = new byte[256];
+         RANDOM_GENERATOR.nextBytes(randomPassword);
+         plainTextPassword = new String(randomPassword);
+      }
+      DigestCallback digestCallback = new DigestCallback();
+      HmacCallback hmacCallback = new HmacCallback();
+      executeCallbacks(digestCallback, hmacCallback);
+      byte[] salt = generateSalt();
+      try {
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(plainTextPassword, salt, 4096,
+                                                                          digestCallback.getDigest(),
+                                                                          hmacCallback.getHmac()));
+         return new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+      } catch (ScramException e) {
+         throw new LoginException();
+      }
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[32];
+      RANDOM_GENERATOR.nextBytes(salt);
+      return salt;
+   }
+
+   private void executeCallbacks(Callback... callbacks) throws LoginException {
+      try {
+         callbackHandler.handle(callbacks);
+      } catch (UnsupportedCallbackException | IOException e) {
+         throw new LoginException();
+      }
+   }
+
+   @Override
+   public boolean commit() throws LoginException {
+      if (userData == null) {
+         throw new LoginException();
+      }
+      subject.getPublicCredentials().add(userData);
+      Set<UserPrincipal> authenticatedUsers = subject.getPrincipals(UserPrincipal.class);
+      UserPrincipal principal = new UserPrincipal(user);
+      principals.add(principal);
+      authenticatedUsers.add(principal);
+      for (UserPrincipal userPrincipal : authenticatedUsers) {
+         Set<String> matchedRoles = roles.get(userPrincipal.getName());
+         if (matchedRoles != null) {
+            for (String entry : matchedRoles) {
+               principals.add(new RolePrincipal(entry));
+            }
+         }
+      }
+      subject.getPrincipals().addAll(principals);
+      return true;
+   }
+
+   @Override
+   public boolean abort() throws LoginException {
+      return true;
+   }
+
+   @Override
+   public boolean logout() throws LoginException {
+      subject.getPrincipals().removeAll(principals);
+      principals.clear();
+      subject.getPublicCredentials().remove(userData);
+      userData = null;
+      return true;
+   }
+
+   /**
+    * Main method that could be used to encrypt given credentials for use in properties files
+    * @param args username password type [iterations]
+    * @throws GeneralSecurityException if any security mechanism is not available on this JVM
+    * @throws ScramException if invalid data is supplied
+    */
+   public static void main(String[] args) throws GeneralSecurityException, ScramException {
+      if (args.length < 2) {
+         System.out.println("Usage: " + SCRAMPropertiesLoginModule.class.getSimpleName() +
+                  " <username> <password> [<iterations>]");
+         System.out.println("\ttype: " + getSupportedTypes());
+         System.out.println("\titerations desired number of iteration (min value: " + MIN_ITERATIONS + ")");
+         return;
+      }
+      String username = args[0];
+      String password = args[1];
+      for (SCRAM scram : SCRAM.values()) {
+         MessageDigest digest = MessageDigest.getInstance(scram.getDigest());
+         Mac hmac = Mac.getInstance(scram.getHmac());
+         byte[] salt = generateSalt();
+         int iterations;
+         if (args.length > 2) {
+            iterations = Integer.parseInt(args[2]);
+            if (iterations < MIN_ITERATIONS) {
+               throw new IllegalArgumentException("minimum of " + MIN_ITERATIONS + " required!");
+            }
+         } else {
+            iterations = MIN_ITERATIONS;
+         }
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, iterations, digest, hmac));
+         System.out.println(username + SEPARATOR_MECHANISM + scram.name() + " = " +

Review comment:
       This is printing the given username as-is, while the client bits added for the outgoing broker-connection stuff does all the string prep reworking...it seems the broker just does a direct lookup of whats received, wouldn't this output or the lookup need to have similar hoop jumping so they will align and the lookup works?
   
   (Elsewhere we just avoided this complexity and required use of ASCII usernames, reducing things to simple substitutions of a couple characters)

##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/AMQPConnectSaslTest.java
##########
@@ -296,4 +342,92 @@ public String getChosenMech() {
       }
    }
 
+   private static final class SCRAMTestAuthenticator implements ProtonSaslAuthenticator {
+
+      private final SCRAM mech;
+      private Sasl sasl;
+      private TestSCRAMServerSASL serverSASL;
+
+      SCRAMTestAuthenticator(SCRAM mech) {
+         this.mech = mech;
+      }
+
+      @Override
+      public void init(NetSocket socket, ProtonConnection protonConnection, Transport transport) {
+         this.sasl = transport.sasl();
+         sasl.server();
+         sasl.allowSkip(false);
+         sasl.setMechanisms(mech.getName());
+         try {
+            serverSASL = new TestSCRAMServerSASL(mech, Logger.getLogger(getClass()));
+         } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError(e);
+         }
+
+      }
+
+      @Override
+      public void process(Handler<Boolean> completionHandler) {
+         String[] remoteMechanisms = sasl.getRemoteMechanisms();
+         int pending = sasl.pending();
+         if (remoteMechanisms.length == 0 || pending == 0) {
+            completionHandler.handle(false);
+            return;
+         }
+         byte[] msg = new byte[pending];
+         sasl.recv(msg, 0, msg.length);
+         byte[] result = serverSASL.processSASL(msg);
+         if (result != null) {
+            sasl.send(result, 0, result.length);
+         }
+         boolean ended = serverSASL.isEnded();
+         System.out.println("end=" + ended);
+         if (ended) {
+            if (succeeded()) {
+               sasl.done(SaslOutcome.PN_SASL_OK);
+            } else {
+               sasl.done(SaslOutcome.PN_SASL_AUTH);
+            }
+            completionHandler.handle(true);
+         } else {
+            completionHandler.handle(false);
+         }
+      }
+
+      @Override
+      public boolean succeeded() {
+         SASLResult result = serverSASL.result();
+         return result != null && result.isSuccess();
+      }
+
+   }
+
+   private static final class TestSCRAMServerSASL extends SCRAMServerSASL {
+
+      TestSCRAMServerSASL(SCRAM mechanism, Logger logger) throws NoSuchAlgorithmException {
+         super(mechanism, logger);
+      }
+
+      @Override
+      public void done() {
+         // nothing to do
+      }
+
+      @Override
+      protected UserData aquireUserData(String userName) throws LoginException {

Review comment:
       Should verify the username was as expected also.

##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;
+
+/**
+ * implements the client part of SASL-SCRAM for broker interconnect
+ */
+public class SCRAMClientSASL implements ClientSASL {
+   private final SCRAM scramType;
+   private final ScramClientFunctionalityImpl client;
+   private final String username;
+   private final String password;
+
+   /**
+    * @param scram the SCRAM mechanism to use
+    * @param username the username for authentication
+    * @param password the password for authentication
+    */
+   public SCRAMClientSASL(SCRAM scram, String username, String password) {
+      Objects.requireNonNull(scram);
+      Objects.requireNonNull(username);
+      Objects.requireNonNull(password);
+      this.username = username;
+      this.password = password;
+      this.scramType = scram;
+      client = new ScramClientFunctionalityImpl(scram.getDigest(), scram.getHmac(), UUID.randomUUID().toString());
+   }
+
+   @Override
+   public String getName() {
+      return scramType.getName();
+   }
+
+   @Override
+   public byte[] getInitialResponse() {
+      try {
+         String firstMessage = client.prepareFirstMessage(username);
+         System.out.println("SCRAMClientSASL.getInitialResponse() >> " + firstMessage);

Review comment:
       Leftover System.out.println

##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;
+
+/**
+ * implements the client part of SASL-SCRAM for broker interconnect
+ */
+public class SCRAMClientSASL implements ClientSASL {
+   private final SCRAM scramType;
+   private final ScramClientFunctionalityImpl client;
+   private final String username;
+   private final String password;
+
+   /**
+    * @param scram the SCRAM mechanism to use
+    * @param username the username for authentication
+    * @param password the password for authentication
+    */
+   public SCRAMClientSASL(SCRAM scram, String username, String password) {
+      Objects.requireNonNull(scram);
+      Objects.requireNonNull(username);
+      Objects.requireNonNull(password);
+      this.username = username;
+      this.password = password;
+      this.scramType = scram;
+      client = new ScramClientFunctionalityImpl(scram.getDigest(), scram.getHmac(), UUID.randomUUID().toString());
+   }
+
+   @Override
+   public String getName() {
+      return scramType.getName();
+   }
+
+   @Override
+   public byte[] getInitialResponse() {
+      try {
+         String firstMessage = client.prepareFirstMessage(username);
+         System.out.println("SCRAMClientSASL.getInitialResponse() >> " + firstMessage);
+         return firstMessage.getBytes(StandardCharsets.US_ASCII);
+      } catch (ScramException e) {
+         throw new DecodeException("prepareFirstMessage failed", e);
+      }
+   }
+
+   @Override
+   public byte[] getResponse(byte[] challenge) {
+      String msg = new String(challenge, StandardCharsets.US_ASCII);
+      System.out.println("SCRAMClientSASL.getResponse() << " + msg);
+      if (client.getState() == State.FIRST_PREPARED) {
+         try {
+            String finalMessage = client.prepareFinalMessage(password, msg);
+            System.out.println("SCRAMClientSASL.getResponse() >> " + finalMessage);

Review comment:
       Leftover System.out.println

##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/AMQPConnectSaslTest.java
##########
@@ -151,6 +164,34 @@ public void testConnectsWithPlain() throws Exception {
       assertArrayEquals(expectedPlainInitialResponse(USER, PASSWD), authenticator.getInitialResponse());
    }
 
+   @Test(timeout = 200000)
+   public void testConnectsWithSCRAM() throws Exception {
+      CountDownLatch serverConnectionOpen = new CountDownLatch(1);
+      SCRAMTestAuthenticator authenticator = new SCRAMTestAuthenticator(SCRAM.SHA512);

Review comment:
       A better test would be to also pass which mechanisms to offer and offer some others (e.g 512, 256, and PLAIN), then you have also verified it prefers selecting 512 when offered.

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));

Review comment:
       Seems odd to go with the less specific one if both exist (though they of course shouldn't really)...especially so as it will already have had to look up the more-specific value first in order to pass it in as the default. Perhaps flip and only do the less specific lookup if needed?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597014464



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }

Review comment:
       Good point, I'll adjust this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814301757


   as far as I can see there is only one error in ScramClientFunctionality and some warning (some are not related to my changes I think), I'll take a look at this tomorrow. If you can enable this checks on the CI it would be good anyways to prevent these to pass unnoticed.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597036140



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       that makes sense. I guess the difference is that the SCRAMPropertiesLoginModule is also setting the roles. In the kerberos case, we just get a KerberosPrincipal. That is the only information that feeds into the the broker realm and it needs to be transformed to be accepted.
   In this case, this is an artemis plugin producing artemis roles and user principals in an artemis broker. I don't think there is any need to be worried, but there may be a need to logout on sasl error.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816307155


   @laeubi I see what happened. the dependency to Artemis-server was indirect through Artemis-client. however the javadoc needed a direct reference after you added some throws on the javadoc reference.
   
   
   I'm handling it.. and I'm merging it.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r585575202



##########
File path: NOTICE
##########
@@ -3,3 +3,8 @@ Copyright [2014-2021] The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the ScramServerFunctionality.java, ScramServerFunctionalityImpl.java,
+ScramException.java,  ScramUtils.java, UserData.java
+is "SCRAM SASL authentication for Java" (https://github.com/ogrebgr/scram-sasl)
+Copyright 2016 Ognyan Bankov, Licensed under the Apache License, Version 2.0

Review comment:
       In a previous comment I pointed to some tests for the SCRAM impl in qpid-broker-j. I was saying I would personally lift from that impl instead if people thought we actually need to adjust the notice file here (as to be even clearer, we definitely wouldnt need to touch the notice file if we did that). Though as I said, I dont think editing the file is needed.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599534312



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       Yeah I specifically hoped there is an example specific to SASL usage (e.g. using SASL-Plain). That would be a good startingpoint as I then could simply use that example, change to SASL-SCRAM-SHA1 and debug where it fails.
   
   Does 'Artemis JMS client uses Artemis own Core protocol' actually means that even not AMQP is used by the JMS client?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785950410


   note the failing builds, the main line still builds on jdk8


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-786043283


   @laeubi instead of opening a new PR.. can you push -f on your original branch, which will update this PR?
   
   you can pretty much 
   ```
   git reset your-other-branch
   git push origin this-branch
   ```


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596993538



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       Adding unit-test would require to implement the client-side as well.. that's a bit out-of-scope here for the moment. It could be added easily later though if desired.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785983738


   OH WOW.. !!! 
   
   This is such a great contribution!
   
   How difficult would be for you to add a test under ./integration-tests?
   
   
   I see you added an example that would work as a test, but if you could add a test it would be great... if you can't let me know and we would figure out what to do.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599332921



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       I have nod added logout on failure and copy the data for further usage so a logout is also performed after successfull auth.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785981638


   can you squash all commits up to now.. it would be easier to review it.
   
   
   ```
   git rebase -I HEAD~6
   # use the editor to squash or fix all commits into one.
   git push origin -f <YOUR-BRANCH-NAME>
   ```


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816674114


   Alternatively of course SHA-1 support can simply added back ;-)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599303571



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       Artemis includes a JMS client but I can't find how it is used, is there an example that uses AMQP+SASL+Artemis JMS Client?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r591105248



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }

Review comment:
       Please see org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule that gives even more spcific error messages. These messages are only apaer in the log and are not propagated to the client.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596987710



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }

Review comment:
       The comment wasnt about the message text, but about whether that prematurely ends the auth process, before the expected challenge-response cycle occurs, perhaps clearly distinguishing it from cases where the user does exist and making it easy to tell that.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi edited a comment on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi edited a comment on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806051272


   > My earlier feedback about lack of unit tests remains.
   
   is there anything specifically you are missing here? The integration test should already cover most of the use-cases I think. The broker-interconnect-testing even verifies it on a very low-level without any additional configuration involved.
   
   > I really would consider just omitting the SCRAM-SHA-1 support at this point personally, I dont see great value in adding it at this 
   
   But whats the value in removing it? It does not simplify the code, it is not enabled by default (so peopel can choose if they want to enable it or not) and it does not remove complexity as it is just another set of algorithms. On the other hand, adding it "later" or let people "just plug in their own support for it" seems way much more effort on the long run. For example the client-side is currently not pluggable.
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic edited a comment on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic edited a comment on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-786043283


   @laeubi instead of opening a new PR.. can you push -f on your original branch, which will update this PR?
   
   you can pretty much 
   ```
   git reset your-other-branch
   git push origin -f this-branch
   ```


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785930111


   I have spitted this PR in 5 commits:
   
   1. Code developed completely by my own with the standard headers added
   2. Code I have taken from  https://github.com/ogrebgr/scram-sasl modified it (e.g. additional exception checks, removed unnecessary parts), that code is originally licensed APL 2.0 and I have keep the original headers there
   3. I reformated my code and the 3rd-party code according to the Artemis checkstyle rules
   4. An example that uses both codes, inspired by the artemis examples
   5. some refactoring that was necessary for handling users+roles
   
   I hope this makes clear whats "my" work and what might be "derived" or "prio" work, as everything is/was Apache licensed I'm not sure if/how notice files need to be addressed here.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599509032



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         DigestCallback digestCallback = new DigestCallback();
+         HmacCallback hmacCallback = new HmacCallback();
+         executeCallbacks(new Callback[] {digestCallback, hmacCallback});
+         byte[] salt = generateSalt();
+         try {
+            ScramUtils.NewPasswordStringData data =
+                     ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, 4096,
+                                                                             digestCallback.getDigest(),
+                                                                             hmacCallback.getHmac()));
+            userData = new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+         } catch (ScramException e) {
+            throw new LoginException();
+         }
+      }
+      return true;
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[24];

Review comment:
       I mainly just thought 24 seemed unusual is all. I belive Qpid Broker-J uses 32, I'd perhaps do the same as as nice power of 2.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-805649731


   @gtully @gemmellr @clebertsuconic I have now updated the PR once again addressing the review comments. I have added SASL-SCRAM Client support as well so it is possible for brokers to authenticate with SASL-SCRAM as well.
   I think this is now ready for a final review.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600734906



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/AMQPConnectSaslTest.java
##########
@@ -151,6 +164,34 @@ public void testConnectsWithPlain() throws Exception {
       assertArrayEquals(expectedPlainInitialResponse(USER, PASSWD), authenticator.getInitialResponse());
    }
 
+   @Test(timeout = 200000)
+   public void testConnectsWithSCRAM() throws Exception {
+      CountDownLatch serverConnectionOpen = new CountDownLatch(1);
+      SCRAMTestAuthenticator authenticator = new SCRAMTestAuthenticator(SCRAM.SHA512);

Review comment:
       If the server does not choose the offered mechanism the test simply fails as it requires SASL-SCRAM in the TestConnector




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599299927



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       btw the spec says:
   
   >  For interoperability, all SCRAM clients and servers MUST implement
   >    the SCRAM-SHA-1 authentication mechanism, i.e., an authentication
   >    mechanism from the SCRAM family that uses the SHA-1 hash function as
   >    defined in [RFC3174].
   
   so removing SHA-1 seems to be not an option if we want compliance with the spec.
   
   About different schemes, the spec mandates that
   
   > Authentication information: Information used to verify an identity
   >       claimed by a SCRAM client.  The authentication information for a
   >       SCRAM identity consists of salt, iteration count, "StoredKey" and
   >       "ServerKey" (as defined in the algorithm overview) **for each
   >       supported cryptographic hash function**.
   
   So I'll add support for storing multiple encrypted forms for the properties module.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-802021765


   > Any idea whats wrong with the J8 build? it complains about missing file but the j11+j14 do not complain...
   
   The JDK8 builds are building the examples under the release profile. The other builds aren't, because the release profile requires JDK8.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-786044680


   @clebertsuconic I don't want to loose the history on that branch, if everything is setup one could simply use "Sqasch-Merge" Button of Github to have a single-commit-change on the master branch.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r591117208



##########
File path: examples/protocols/amqp/sasl-scram/sasl-server/src/main/resources/artemis-users.properties
##########
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+test = ENC(VeEFPtxYIGIS0VA7e+W5+LpdLmazpcLH:4096:rIPD9cVvOoVJqzD7u4/qRMW1xGwILRG90g2OtWmn8T0=:7k8fGWO1zWPuZF0pzDCYnDCtmaJxLptqHS26SNsbGHU=)

Review comment:
       ENC is not bound to any specific format (even Artemis supports different formats for this) and is just a marker that is is encoded. Its very unlikley someone will create this strings by hand thus the generator was added to create this as it is done with the "standard" PropertiesLoginModule.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816692853


   @gtully the examples are simple main classes, in the Eclipse IDE for example I just rightclick > run as java


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600734275



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         userData = generateUserData(password);
+      }
+      return true;
+   }
+
+   private UserData generateUserData(String plainTextPassword) throws LoginException {
+      if (plainTextPassword == null) {
+         // if the user is not available (or the password) generate a random password here so an
+         // attacker can't
+         // distinguish between a missing username and a wrong password
+         byte[] randomPassword = new byte[256];
+         RANDOM_GENERATOR.nextBytes(randomPassword);
+         plainTextPassword = new String(randomPassword);
+      }
+      DigestCallback digestCallback = new DigestCallback();
+      HmacCallback hmacCallback = new HmacCallback();
+      executeCallbacks(digestCallback, hmacCallback);
+      byte[] salt = generateSalt();
+      try {
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(plainTextPassword, salt, 4096,
+                                                                          digestCallback.getDigest(),
+                                                                          hmacCallback.getHmac()));
+         return new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+      } catch (ScramException e) {
+         throw new LoginException();
+      }
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[32];
+      RANDOM_GENERATOR.nextBytes(salt);
+      return salt;
+   }
+
+   private void executeCallbacks(Callback... callbacks) throws LoginException {
+      try {
+         callbackHandler.handle(callbacks);
+      } catch (UnsupportedCallbackException | IOException e) {
+         throw new LoginException();
+      }
+   }
+
+   @Override
+   public boolean commit() throws LoginException {
+      if (userData == null) {
+         throw new LoginException();
+      }
+      subject.getPublicCredentials().add(userData);
+      Set<UserPrincipal> authenticatedUsers = subject.getPrincipals(UserPrincipal.class);
+      UserPrincipal principal = new UserPrincipal(user);
+      principals.add(principal);
+      authenticatedUsers.add(principal);
+      for (UserPrincipal userPrincipal : authenticatedUsers) {
+         Set<String> matchedRoles = roles.get(userPrincipal.getName());
+         if (matchedRoles != null) {
+            for (String entry : matchedRoles) {
+               principals.add(new RolePrincipal(entry));
+            }
+         }
+      }
+      subject.getPrincipals().addAll(principals);
+      return true;
+   }
+
+   @Override
+   public boolean abort() throws LoginException {
+      return true;
+   }
+
+   @Override
+   public boolean logout() throws LoginException {
+      subject.getPrincipals().removeAll(principals);
+      principals.clear();
+      subject.getPublicCredentials().remove(userData);
+      userData = null;
+      return true;
+   }
+
+   /**
+    * Main method that could be used to encrypt given credentials for use in properties files
+    * @param args username password type [iterations]
+    * @throws GeneralSecurityException if any security mechanism is not available on this JVM
+    * @throws ScramException if invalid data is supplied
+    */
+   public static void main(String[] args) throws GeneralSecurityException, ScramException {
+      if (args.length < 2) {
+         System.out.println("Usage: " + SCRAMPropertiesLoginModule.class.getSimpleName() +
+                  " <username> <password> [<iterations>]");
+         System.out.println("\ttype: " + getSupportedTypes());
+         System.out.println("\titerations desired number of iteration (min value: " + MIN_ITERATIONS + ")");
+         return;
+      }
+      String username = args[0];
+      String password = args[1];
+      for (SCRAM scram : SCRAM.values()) {
+         MessageDigest digest = MessageDigest.getInstance(scram.getDigest());
+         Mac hmac = Mac.getInstance(scram.getHmac());
+         byte[] salt = generateSalt();
+         int iterations;
+         if (args.length > 2) {
+            iterations = Integer.parseInt(args[2]);
+            if (iterations < MIN_ITERATIONS) {
+               throw new IllegalArgumentException("minimum of " + MIN_ITERATIONS + " required!");
+            }
+         } else {
+            iterations = MIN_ITERATIONS;
+         }
+         ScramUtils.NewPasswordStringData data =
+                  ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, iterations, digest, hmac));
+         System.out.println(username + SEPARATOR_MECHANISM + scram.name() + " = " +

Review comment:
       For the SCRAMPropertiesLoginModule one needs to use "safe" characters. If special names are required most likely a more advanced approach is necessary.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597036899



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       Adding unit tests for the code for the very functionality you are adding is clearly not 'out of scope'.
   
   I've also already pointed you at some unit tests for this very same broker behaviour that you are adding, which could easily be used 'for inspiration'. 
   
   You are also using a client here in your systest that has it, and which that the library you have 'taken inspiration from' actually lifted its own client impl from to begin with.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic edited a comment on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic edited a comment on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785981638


   can you squash all commits up to now.. it would be easier to review it.
   
   Unless you intend to keep them separated.. but a commit just to fix check style could be squashed... 
   
   
   you could keep commits separated while under review.. but right now I'm finding it difficult to comment on the changes.
   
   
   ```
   git rebase -I HEAD~6
   # use the editor to squash or fix all commits into one.
   git push origin -f <YOUR-BRANCH-NAME>
   ```


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599595324



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       Thanks for the hint, I think org.apache.activemq.artemis.tests.integration.amqp.connect.AMQPConnectSaslTest is what I'm looking for... 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816680173


   leave it with me, I will push a fix.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599506786



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       I believe there are some tests in the 'connect' package that will be using PLAIN. Dont think the examples do, in examples/features/broker-connection, which could be an improvement to make.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-795009504


   @gemmellr thanks for the feedback, I have addressed the following issues:
   
   1. dropped SHA512 as there are no client to test with
   2. remove unnecessary notice file entries
   3. spaces versus tabs
   4. itest now has more "test-style" assumptions testing more scenarios
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597013469



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       The tests names could be more descriptive of what they are doing. I did eventually figure out that 'testEncryptedWorksOnlyWithMechanism' and 'testEncryptedWorksWithMechanism' are 2 paired tests checking that login for the 'test' user only works with the SCRAM-SHA-256 mechanism since the details were presumably generated for that mech and can only work with that (goes back to the comment about indicating how the file contents were created).
   
   That makes me think its a bad idea for it the login module to be able support more than one mechanism. The broker generally shouldnt advertise e.g both SCRAM-SHA1 and SCRAM-SHA-256 (though what is advertised is obviously under the configs control) when using a single module if the credentials for a given user can only work with one SCRAM type when stored they way they should be (obviously with plaintext storage it could do any). I think it might make more sense to have mechanism-specific modules given that.
   
   To that end I would perhaps just skip the SCRAM-SHA-1 support and rename everything for 256. It feels like few should consider using it SHA-1 at this point a newly introduced setup instead of requiring 256.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596992275



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       There are two "phases" in the Artemis Workflow (you can take a look at kerberos auth for example that uses a similar scheme:
   
   1. The user autenticates/login with username-password on the **transport-layer** (AMQP). That means, at this point the user is not logged in on the application level, we only collect the user and group principals here.
   2. If the user has passed transport authentication Artemis asks for the user credentials on the **application-layer**, normally this would for example query a user-database. Now the aquired data from phase-1 are passed to the application layer and the user is logged in with his naem+roles.
   
   That's why there are two provider: SCRAMLoginModule for the application layer and SCRAMPropertiesLoginModule for the transport-layer.
   
   So if the login succeeds in an intermediate SASL-Phase but fails later the information is simply thrown away and never gets to the application layer. This allows users to plugin alternative User-Information sources (e.g. fetching from a database or LDAP or whatever) instead of the SCRAMPropertiesLoginModule.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814126686


   I would like to run a test suite before merging anyway.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806401816


   I have added unit-test and used the properties/stringprep for username encoding


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic edited a comment on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic edited a comment on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814126306


   @gtully can we squash before merged? there are 23 commits on this PR.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-788688135


   Any idea the J14 build fails?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599298651



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         DigestCallback digestCallback = new DigestCallback();
+         HmacCallback hmacCallback = new HmacCallback();
+         executeCallbacks(new Callback[] {digestCallback, hmacCallback});
+         byte[] salt = generateSalt();
+         try {
+            ScramUtils.NewPasswordStringData data =
+                     ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, 4096,
+                                                                             digestCallback.getDigest(),
+                                                                             hmacCallback.getHmac()));
+            userData = new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+         } catch (ScramException e) {
+            throw new LoginException();
+         }
+      }
+      return true;
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[24];

Review comment:
       No specific reason, the SASL-SCRAM-FOR-JAVA uses the same size so I used it here. Any suggestions or concerns for an alternative size? I checked the spec and it does not gives any advice or recommendation just that a salt should be used:
   
   > Salt: A random octet string that is combined with a password
   >       before applying a one-way encryption function.  This value is used
   >       to protect passwords that are stored in an authentication
   >       database.
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601438306



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();

Review comment:
       Shouldnt it just throw an exception then? I see no reason to magic up a username.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816308150


   @laeubi nice contribution BTW! Kudos and thanks for this! 
   
   
   We own you a few rounds of beers if we ever connect face to face.. say if we ever go to a same conference or something.. thanks a lot...
   
   
   it would be awesome to keep getting contributions from you... really nice!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600354874



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/Normalizer.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2011 Glenn Maynard
+ * <p>
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Dynamically-loaded interface for java.text.Normalizer(NFKC); it's missing in non-bleeding-edge
+ * versions of Android and we can get by without it.
+ */
+@SuppressWarnings({ "SpellCheckingInspection", "JavaDoc" })
+class Normalizer {

Review comment:
       btw: thanks for your patience and great work on this :-)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-816281196


   related discussion: https://github.com/apache/activemq-artemis/pull/3531


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-800811822


   @clebertsuconic @gtully @gemmellr how could we proceed here?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r585432662



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   /**
+    *
+    */

Review comment:
       Is this needed?

##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/resources/META-INF/services/org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory
##########
@@ -1,4 +1,7 @@
 org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASLFactory
 org.apache.activemq.artemis.protocol.amqp.sasl.PlainServerSASLFactory
 org.apache.activemq.artemis.protocol.amqp.sasl.GSSAPIServerSASLFactory
-org.apache.activemq.artemis.protocol.amqp.sasl.ExternalServerSASLFactory
\ No newline at end of file
+org.apache.activemq.artemis.protocol.amqp.sasl.ExternalServerSASLFactory
+org.apache.activemq.artemis.protocol.amqp.sasl.scram.SHA1SCRAMServerSASLFactory
+org.apache.activemq.artemis.protocol.amqp.sasl.scram.SHA256SCRAMServerSASLFactory
+org.apache.activemq.artemis.protocol.amqp.sasl.scram.SHA512CRAMServerSASLFactory

Review comment:
       Last class name is 'wrong', its missing the S in SCRAM: _SHA512**S**CRAMServerSASLFactory_.

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/PrincipalsCallback.java
##########
@@ -16,31 +16,30 @@
  */
 package org.apache.activemq.artemis.spi.core.security.jaas;
 
-import javax.security.auth.callback.Callback;
 import java.security.Principal;
 
+import javax.security.auth.callback.Callback;
+
 /**
- * A Callback for kerberos peer principal.
+ * A Callback for getting the peer principal.

Review comment:
       principal**s**

##########
File path: NOTICE
##########
@@ -3,3 +3,8 @@ Copyright [2014-2021] The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the ScramServerFunctionality.java, ScramServerFunctionalityImpl.java,
+ScramException.java,  ScramUtils.java, UserData.java
+is "SCRAM SASL authentication for Java" (https://github.com/ogrebgr/scram-sasl)
+Copyright 2016 Ognyan Bankov, Licensed under the Apache License, Version 2.0

Review comment:
       I dont believe this is necessary.
   
   The NOTICE file is essentially for 'required legal notifications' that aren't satisfied otherwise already. It is for example sometimes used to move copyright notices for submissions *by the copyright owner/agent* out of the related source files, since it is preferred they not have any. For entirely 3rd party items though as in this case, the original header is to be left as is, meaning this copyright notice is already conveyed by the files themselves, which are still ALv2 and so needn't have that called out specifically (which would also be in the LICENCE file if it were). So I think this isnt needed. 
   
   If we thought it were needed, I'd likely lift the qpid-broker-j code I pointed to (for the tests which this code still lacks) instead.

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java
##########
@@ -67,18 +68,22 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
             CertificateCallback certCallback = (CertificateCallback) callback;
 
             certCallback.setCertificates(getCertsFromConnection(remotingConnection));
-         } else if (callback instanceof Krb5Callback) {
-            Krb5Callback krb5Callback = (Krb5Callback) callback;
+         } else if (callback instanceof PrincipalsCallback) {
+            PrincipalsCallback krb5Callback = (PrincipalsCallback) callback;

Review comment:
       Renaming the variable as well as changing the type would seem appropriate, its now somewhat misleading.

##########
File path: examples/protocols/amqp/pom.xml
##########
@@ -51,6 +51,7 @@ under the License.
             <module>proton-clustered-cpp</module>
             <module>queue</module>
             <module>proton-ruby</module>
+			<module>sasl-scram</module>

Review comment:
       Has a tab instead of spaces.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-client/readme.md
##########
@@ -0,0 +1,3 @@
+# Artemis SASL-SCRAM Server and Client Example
+
+demonstrate the usage of SASL-SCRAM authentication with Artemis-MQ

Review comment:
       ActiveMQ Artemis or just Artemis, not Artemis-MQ.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-client/src/main/java/org/apache/activemq/artemis/jms/example/QPIDClient.java
##########
@@ -0,0 +1,53 @@
+/*
+ * <p>
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.jms.example;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class QPIDClient {
+	public static void main(String[] args) throws JMSException {
+		for (String method : new String[] { "SCRAM-SHA-1", "SCRAM-SHA-256" }) {
+			ConnectionFactory connectionFactory = new JmsConnectionFactory(
+					"amqp://localhost:5672?amqp.saslMechanisms=" + method);
+			Connection connection;
+			if ("SCRAM-SHA-256".equals(method)) {
+				connection = connectionFactory.createConnection("test", "test");

Review comment:
       Having a util method that is called twice passing the mech and user/pass args would be nicer/clearer than the for+if.

##########
File path: examples/protocols/amqp/sasl-scram/pom.xml
##########
@@ -0,0 +1,33 @@
+<?xml version='1.0'?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+	license agreements. See the NOTICE file distributed with this work for additional 
+	information regarding copyright ownership. The ASF licenses this file to 
+	you under the Apache License, Version 2.0 (the "License"); you may not use 
+	this file except in compliance with the License. You may obtain a copy of 
+	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+	by applicable law or agreed to in writing, software distributed under the 
+	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+	OF ANY KIND, either express or implied. See the License for the specific 
+	language governing permissions and limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"

Review comment:
       File has tabs instead of spaces.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-client/pom.xml
##########
@@ -0,0 +1,41 @@
+<?xml version='1.0'?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+	license agreements. See the NOTICE file distributed with this work for additional 
+	information regarding copyright ownership. The ASF licenses this file to 
+	you under the Apache License, Version 2.0 (the "License"); you may not use 
+	this file except in compliance with the License. You may obtain a copy of 
+	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+	by applicable law or agreed to in writing, software distributed under the 
+	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+	OF ANY KIND, either express or implied. See the License for the specific 
+	language governing permissions and limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"

Review comment:
       File has tabs instead of spaces.

##########
File path: tests/integration-tests/src/test/resources/broker-saslscram.xml
##########
@@ -0,0 +1,44 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<configuration

Review comment:
       File uses tabs.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-server/readme.md
##########
@@ -0,0 +1,3 @@
+# Artemis SASL-SCRAM Server and Client Example
+
+demonstrate the usage of SASL-SCRAM authentication with Artemis-MQ

Review comment:
       ActiveMQ Artemis or just Artemis, not Artemis-MQ.

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }
+      if (PasswordMaskingUtil.isEncMasked(password)) {
+         String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR);
+         userData = new UserData(unwrap[0], Integer.parseInt(unwrap[1]), unwrap[2], unwrap[3]);
+      } else {
+         DigestCallback digestCallback = new DigestCallback();
+         HmacCallback hmacCallback = new HmacCallback();
+         executeCallbacks(new Callback[] {digestCallback, hmacCallback});
+         byte[] salt = generateSalt();
+         try {
+            ScramUtils.NewPasswordStringData data =
+                     ScramUtils.byteArrayToStringData(ScramUtils.newPassword(password, salt, 4096,
+                                                                             digestCallback.getDigest(),
+                                                                             hmacCallback.getHmac()));
+            userData = new UserData(data.salt, data.iterations, data.serverKey, data.storedKey);
+         } catch (ScramException e) {
+            throw new LoginException();
+         }
+      }
+      return true;
+   }
+
+   private static byte[] generateSalt() {
+      byte[] salt = new byte[24];

Review comment:
       Any reason to use 24 specifically rather than say 32?

##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   private static final String SEPARATOR = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(new Callback[] {nameCallback});
+      user = nameCallback.getName();
+      if (user == null) {
+         throw new FailedLoginException("User is null");
+      }
+      String password = users.getProperty(user);
+      if (password == null) {
+         throw new FailedLoginException("User does not exist: " + user);
+      }

Review comment:
       Its generally nice not to give away that specific users dont exist, as that can be used to determine users that do. I've seen other impls essentially continue in this case and generate a salt, so that the SCRAM process continues and only fails later in the same way as an incorrect password being specified, rather than clearly failing early because the user didn't exist.

##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SHA512CRAMServerSASLFactory.java
##########
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+
+/**
+ * provides SASL SCRAM-SHA512
+ */
+public class SHA512CRAMServerSASLFactory extends SCRAMServerSASLFactory {

Review comment:
       Class name is missing the S in SCRAM as noted for the service loader config.

##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       This is the wrong package for this test, the 'connect' package is for testing of the brokers outbound connection abilities. The base amqp package or a new scram specific one would seem best.
   
   This raises another point though - the broker wont be able to connect to another Artemis instance if it is configured to use this SCRAM-SHA support, since it lacks the client side mechanism support.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-server/pom.xml
##########
@@ -0,0 +1,46 @@
+<?xml version='1.0'?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+	license agreements. See the NOTICE file distributed with this work for additional 
+	information regarding copyright ownership. The ASF licenses this file to 
+	you under the Apache License, Version 2.0 (the "License"); you may not use 
+	this file except in compliance with the License. You may obtain a copy of 
+	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+	by applicable law or agreed to in writing, software distributed under the 
+	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+	OF ANY KIND, either express or implied. See the License for the specific 
+	language governing permissions and limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"

Review comment:
       File has tabs instead of spaces.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-server/src/main/resources/artemis-users.properties
##########
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+test = ENC(VeEFPtxYIGIS0VA7e+W5+LpdLmazpcLH:4096:rIPD9cVvOoVJqzD7u4/qRMW1xGwILRG90g2OtWmn8T0=:7k8fGWO1zWPuZF0pzDCYnDCtmaJxLptqHS26SNsbGHU=)

Review comment:
       Might be good for the example to explain how this was created, here and/or in the readme.
   
   Separately, that points to the lack of new documentation around this, which will need added.
   
   Also, I wonder if the ENC(..) format used here likely to confuse people into thinking it is masked in the same way other user config can be, which I believe uses a similar ENC(..) format string, when it is obviously handled in a very different way.

##########
File path: examples/protocols/amqp/sasl-scram/sasl-client/src/main/java/org/apache/activemq/artemis/jms/example/QPIDClient.java
##########
@@ -0,0 +1,53 @@
+/*
+ * <p>
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.jms.example;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class QPIDClient {
+	public static void main(String[] args) throws JMSException {
+		for (String method : new String[] { "SCRAM-SHA-1", "SCRAM-SHA-256" }) {
+			ConnectionFactory connectionFactory = new JmsConnectionFactory(
+					"amqp://localhost:5672?amqp.saslMechanisms=" + method);
+			Connection connection;
+			if ("SCRAM-SHA-256".equals(method)) {
+				connection = connectionFactory.createConnection("test", "test");
+			} else {
+				connection = connectionFactory.createConnection("hello", "ogre1234");
+			}
+			try {
+				Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+				Queue queue = session.createQueue("exampleQueue");
+				MessageProducer sender = session.createProducer(queue);
+				sender.send(session.createTextMessage("Hello " + method));
+				connection.start();
+				MessageConsumer consumer = session.createConsumer(queue);
+				TextMessage m = (TextMessage) consumer.receive(5000);
+				System.out.println("message = " + m.getText());
+			} finally {
+				connection.close();
+			}

Review comment:
       Perhaps a try-with-resources instead?

##########
File path: tests/integration-tests/src/test/resources/artemis-scram-users.properties
##########
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+test = ENC(VeEFPtxYIGIS0VA7e+W5+LpdLmazpcLH:4096:rIPD9cVvOoVJqzD7u4/qRMW1xGwILRG90g2OtWmn8T0=:7k8fGWO1zWPuZF0pzDCYnDCtmaJxLptqHS26SNsbGHU=)

Review comment:
       Similar to the example, perhaps worth explaining how this was generated / what it represents.

##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testSendReceive() throws JMSException {

Review comment:
       Same comments as the example since this is essentially the same code.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785987266


   I just had some difficulties getting the embedded server running with qpid on the classpath due to dependencies conflicts so I spited them in two part in the example but will try to investigate how this could be combined into one combined itest.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785989168


   There are lots of tests that use the Qpid JMS client already, there should be no real dep issues there.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597050819



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       About the logout, its a bit problematic as far as I can see there is no notification e.g. if the client never sends the final message. and as the kerberos also do never logouts I choose to first keep it simple here. Actually the logout needs to be bound to the application-level as well but I also don't see an easy path here without even more refactoring.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599632117



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/SCRAM.java
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.scram;
+
+/**
+ * Defines sets of known SCRAM types with methods to fetch matching digest and hmac names
+ */
+public enum SCRAM {
+                   SHA1,
+                   SHA256,
+                   SHA512;

Review comment:
       As cyrus-sasl seems to support it already that means there are actually AMQP 1.0 clients that support it (qpid-proton c/cpp/python/etc use cyrus-sasl), just not qpid-jms yet.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597141793



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       The unitest should at least cover that cases even though its not likely to be used. its not meant as an example for a productive configuration. The same applies for the example itself. It demonstrates the plaintext usage and the encrypted usage I don't see what this should be "bad" in any way.
   
   > Clients shouldnt need apriori knowledge of what mechs the server is storing their details for in general. 
   
   that's how SASL_SCRAM works. this way and there is no way around it. You can only authenticate with a mechanism that was negotiated with the server before, SASL-SCRAM is not meant to "upgrade" or something like that. That's intrinsic to the mechanism itself and nothing that could be negotiated.
   
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] asfgit closed pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
asfgit closed pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806806500


   I'm going to leave further review here for some of the main broker maintainers. I think it needs some more eyes to look it over at this point (e.g I note that as I know little about the JAAS login bits, I've not been looking at that aspect), perhaps input from someone who knows the user creation stuff would be good, certainly some other folks thoughts on SCRAM-SHA-1 support would be useful.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596931243



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       Christoph, this login call has me wondering.... here we have a successfully authenticated subject from a JAAS perspective but have not yet completed the SASL exchange. Could this be a problem? If there are any other login modules in that realm the semantics may be broken a little.
   When I thought of doing something similar, I imagined the callback handlers would provide the mechanism to perform challenge/response - ie: it would all happen as part of the login call. Either through a fancy handler that would expose the state machine or some series/chain of handlers that represent the state transitions.
   I would need to do a little proof of concept to verify that would work... but is that something you considered?
   I am not certain that the current use of login it is a problem, but it does seem odd.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r599548853



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/sasl/SaslScramTest.java
##########
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.sasl;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.exceptions.JMSSecuritySaslException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test SASL-SCRAM Support
+ */
+public class SaslScramTest {
+
+   private static EmbeddedActiveMQ BROKER;
+
+   @BeforeClass
+   public static void startBroker() throws Exception {
+      String loginConfPath = new File(SaslScramTest.class.getResource("/login.config").toURI()).getAbsolutePath();
+      System.out.println(loginConfPath);
+      System.setProperty("java.security.auth.login.config", loginConfPath);
+      BROKER = new EmbeddedActiveMQ();
+      BROKER.setConfigResourcePath(SaslScramTest.class.getResource("/broker-saslscram.xml").toExternalForm());
+      BROKER.setSecurityManager(new ActiveMQJAASSecurityManager("artemis-sasl-scram"));
+      BROKER.start();
+   }
+
+   @AfterClass
+   public static void shutdownBroker() throws Exception {
+      BROKER.stop();
+   }
+
+   @Test
+   public void testUnencryptedWorksWithAllMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "hello", "ogre1234");
+      sendRcv("SCRAM-SHA-256", "hello", "ogre1234");
+   }
+
+   @Test(expected = JMSSecuritySaslException.class)
+   public void testEncryptedWorksOnlyWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-1", "test", "test");
+   }
+
+   @Test
+   public void testEncryptedWorksWithMechanism() throws JMSException {
+      sendRcv("SCRAM-SHA-256", "test", "test");
+   }

Review comment:
       I think that probably just betrays its age, when SHA-1 was still widely recommended. The SCRAM-SHA-256 RFC specifically opens talking to it having expected longer longeveity than SHA-1 based mechs, and also later recommends transition to SHA-256. Technically one could implement it (e.g seperately in its own module) without offering it normally and still satisfy that original wording hehe. I'm not agaisnt it being there, though I dont see anyone needing it at this point, removing it was mostly a simple reoute to resolve the multi-types issue and adopt single-mech-per-module semantics in one swoop.
   
   The latter wording doesnt surprise me, its jsut how SASL is meant to work...if you offer mechanisms that means they work, and the client is free to pick whatever one they can/want and it should work.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] clebertsuconic commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
clebertsuconic commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-814298042


   this is failing to generate the javadoc:
   
   ```
   [ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:3.0.1:javadoc (default-cli) on project artemis-amqp-protocol: An error has occurred in Javadoc report generation: 
   [ERROR] Exit code: 1 - /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:180: warning: no @return
   [ERROR]    public ProtonClientProtocolManager createClientManager() {
   [ERROR]                                       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:192: warning: no @param for remotingConnection
   [ERROR]    public ConnectionEntry createOutgoingConnectionEntry(Connection remotingConnection) {
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:192: warning: no @return
   [ERROR]    public ConnectionEntry createOutgoingConnectionEntry(Connection remotingConnection) {
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:354: warning: no @return
   [ERROR]    public boolean isUseModifiedForTransientDeliveryErrors() {
   [ERROR]                   ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:362: warning: no @param for amqpUseModifiedForTransientDeliveryErrors
   [ERROR]    public ProtonProtocolManager setAmqpUseModifiedForTransientDeliveryErrors(boolean amqpUseModifiedForTransientDeliveryErrors) {
   [ERROR]                                 ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java:362: warning: no @return
   [ERROR]    public ProtonProtocolManager setAmqpUseModifiedForTransientDeliveryErrors(boolean amqpUseModifiedForTransientDeliveryErrors) {
   [ERROR]                                 ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerSenderContext.java:489: warning: no @param for messageReference
   [ERROR]    public int deliverMessage(final MessageReference messageReference, final ServerConsumer consumer) throws Exception {
   [ERROR]               ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerSenderContext.java:489: warning: no @param for consumer
   [ERROR]    public int deliverMessage(final MessageReference messageReference, final ServerConsumer consumer) throws Exception {
   [ERROR]               ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerSenderContext.java:489: warning: no @return
   [ERROR]    public int deliverMessage(final MessageReference messageReference, final ServerConsumer consumer) throws Exception {
   [ERROR]               ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerSenderContext.java:489: warning: no @throws for java.lang.Exception
   [ERROR]    public int deliverMessage(final MessageReference messageReference, final ServerConsumer consumer) throws Exception {
   [ERROR]               ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java:175: warning: no description for @return
   [ERROR]     * @return
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPLargeMessage.java:177: warning: no @param for reference
   [ERROR]    public void checkReference(MessageReference reference) {
   [ERROR]                ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPLargeMessage.java:184: warning: no @return
   [ERROR]    public int getPositionAfterDeliveryAnnotations() {
   [ERROR]               ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPLargeMessage.java:199: warning: no @return
   [ERROR]    public ByteBuf inspectTemporaryBuffer() {
   [ERROR]                   ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:261: warning: no @return
   [ERROR]    protected ApplicationProperties getDecodedApplicationProperties() {
   [ERROR]                                    ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:414: warning: no @return
   [ERROR]    public final String toDebugString() {
   [ERROR]                        ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:726: warning: no @param for reference
   [ERROR]    public ReadableBuffer getSendBuffer(int deliveryCount, MessageReference reference) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:748: warning: no @param for deliveryCount
   [ERROR]    protected ReadableBuffer createDeliveryCopy(int deliveryCount, DeliveryAnnotations deliveryAnnotations) {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:748: warning: no @param for deliveryAnnotations
   [ERROR]    protected ReadableBuffer createDeliveryCopy(int deliveryCount, DeliveryAnnotations deliveryAnnotations) {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:748: warning: no @return
   [ERROR]    protected ReadableBuffer createDeliveryCopy(int deliveryCount, DeliveryAnnotations deliveryAnnotations) {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java:228: warning: no @param for coreMessageObjectPools
   [ERROR]    public AMQPMessage(long messageFormat, TypedProperties extraProperties, CoreMessageObjectPools coreMessageObjectPools) {
   [ERROR]           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:30: warning: no @param for message
   [ERROR]    public static Object getDeliveryAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:30: warning: no @param for symbol
   [ERROR]    public static Object getDeliveryAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:30: warning: no @return
   [ERROR]    public static Object getDeliveryAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:35: warning: no @param for message
   [ERROR]    public static Object getMessageAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:35: warning: no @param for symbol
   [ERROR]    public static Object getMessageAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:35: warning: no @return
   [ERROR]    public static Object getMessageAnnotationProperty(AMQPMessage message, Symbol symbol) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:40: warning: no @param for message
   [ERROR]    public static Header getCurrentHeader(AMQPMessage message) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:40: warning: no @return
   [ERROR]    public static Header getCurrentHeader(AMQPMessage message) {
   [ERROR]                         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:45: warning: no @param for message
   [ERROR]    public static ApplicationProperties getDecodedApplicationProperties(AMQPMessage message) {
   [ERROR]                                        ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:45: warning: no @return
   [ERROR]    public static ApplicationProperties getDecodedApplicationProperties(AMQPMessage message) {
   [ERROR]                                        ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:50: warning: no @param for message
   [ERROR]    public static int getRemainingBodyPosition(AMQPMessage message) {
   [ERROR]                      ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:50: warning: no @return
   [ERROR]    public static int getRemainingBodyPosition(AMQPMessage message) {
   [ERROR]                      ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:55: warning: no @param for message
   [ERROR]    public static Properties getCurrentProperties(AMQPMessage message) {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessageBrokerAccessor.java:55: warning: no @return
   [ERROR]    public static Properties getCurrentProperties(AMQPMessage message) {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java:617: warning: no @param for address
   [ERROR]    public void flow(final SimpleString address,
   [ERROR]                ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java:617: warning: no @param for runnable
   [ERROR]    public void flow(final SimpleString address,
   [ERROR]                ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorControllerTarget.java:352: warning: no description for @param
   [ERROR]     * @param ref
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorControllerTarget.java:353: warning: no description for @param
   [ERROR]     * @param reason
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorControllerTarget.java:362: warning: no description for @param
   [ERROR]     * @param message
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorControllerTarget.java:363: warning: no description for @param
   [ERROR]     * @param context
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorControllerTarget.java:364: warning: no description for @param
   [ERROR]     * @param refs
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @param for refill
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @param for threshold
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @param for receiver
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @param for connection
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @param for context
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:116: warning: no @return
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:128: warning: no @param for refill
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:128: warning: no @param for threshold
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:128: warning: no @param for receiver
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:128: warning: no @param for connection
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonAbstractReceiver.java:128: warning: no @return
   [ERROR]    public static Runnable createCreditRunnable(int refill,
   [ERROR]                           ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @param for to
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @param for address
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @param for queue
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @param for event
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @param for body
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/connect/mirror/AMQPMirrorMessageFactory.java:51: warning: no @return
   [ERROR]    public static Message createMessage(String to, SimpleString address, SimpleString queue, Object event, Object body) {
   [ERROR]                          ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/coreWrapper/CoreMessageWrapper.java:121: warning: no @return
   [ERROR]    protected ActiveMQBuffer getReadBodyBuffer() {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/coreWrapper/CoreMessageWrapper.java:132: warning: no @return
   [ERROR]    protected ActiveMQBuffer getWriteBodyBuffer() {
   [ERROR]                             ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java:92: warning: no description for @param
   [ERROR]     * @param consumer
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java:93: warning: no description for @param
   [ERROR]     * @param queueName
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLFactory.java:37: warning: no description for @param
   [ERROR]     * @param server
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLFactory.java:38: warning: no description for @param
   [ERROR]     * @param manager
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLFactory.java:39: warning: no description for @param
   [ERROR]     * @param connection
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLFactory.java:40: warning: no description for @param
   [ERROR]     * @param remotingConnection
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java:68: warning: no description for @param
   [ERROR]     * @param user
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java:69: warning: no description for @param
   [ERROR]     * @param password
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java:71: warning: no @return
   [ERROR]    protected boolean authenticate(String user, String password) {
   [ERROR]                      ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramClientFunctionality.java:47: error: invalid use of @return
   [ERROR]     * @return true if the server's message is valid, false otherwise
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramClientFunctionality.java:49: warning: no @throws for org.apache.activemq.artemis.spi.core.security.scram.ScramException
   [ERROR]    void checkServerFinalMessage(String serverFinalMessage) throws ScramException;
   [ERROR]         ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionality.java:34: warning: no description for @throws
   [ERROR]     * @throws ScramException
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionality.java:49: warning: no description for @throws
   [ERROR]     * @throws ScramException
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionalityImpl.java:89: warning: no description for @throws
   [ERROR]     * @throws ScramException
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionalityImpl.java:56: warning: no description for @throws
   [ERROR]     * @throws NoSuchAlgorithmException
   [ERROR]       ^
   [ERROR] /home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionalityImpl.java:67: warning: no description for @throws
   [ERROR]     * @throws NoSuchAlgorithmException
   [ERROR]       ^
   [ERROR] 
   [ERROR] Command line was: /home/jenkins-slave/tools/hudson.model.JDK/JDK8/jre/../bin/javadoc @options @packages
   [ERROR] 
   [ERROR] Refer to the generated Javadoc files in '/home/jenkins-slave/workspace/novm-artemis-param/artemis-protocols/artemis-amqp-protocol/target/site/apidocs' dir.
   [ERROR] 
   [ERROR] -> [Help 1]
   [ERROR] 
   [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
   [ERROR] Re-run Maven using the -X switch to enable full debug logging.
   [ERROR] 
   [ERROR] For more information about the errors and possible solutions, please read the following articles:
   [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
   [ERROR] 
   [ERROR] After correcting the problems, you can resume the build with the command
   [ERROR]   mvn <args> -rf :artemis-amqp-protocol
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r597042491



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASLFactory.java
##########
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
+import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
+import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.security.jaas.DigestCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.HmacCallback;
+import org.apache.activemq.artemis.spi.core.security.jaas.SCRAMMechanismCallback;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.jboss.logging.Logger;
+
+/**
+ * abstract class that implements the SASL-SCRAM authentication scheme, concrete implementations
+ * must supply the {@link SCRAM} type to use and be register via SPI
+ */
+public abstract class SCRAMServerSASLFactory implements ServerSASLFactory {
+
+   private final Logger logger = Logger.getLogger(getClass());
+   private final SCRAM scramType;
+
+   public SCRAMServerSASLFactory(SCRAM scram) {
+      this.scramType = scram;
+   }
+
+   @Override
+   public String getMechanism() {
+      return scramType.getName();
+   }
+
+   @Override
+   public boolean isDefaultPermitted() {
+      return false;
+   }
+
+   @Override
+   public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
+                            RemotingConnection remotingConnection) {
+      try {
+         if (manager instanceof ProtonProtocolManager) {
+            ScramServerFunctionalityImpl scram =
+                     new ScramServerFunctionalityImpl(scramType.getDigest(), scramType.getHmac(),
+                                                      UUID.randomUUID().toString());
+            String loginConfigScope = ((ProtonProtocolManager) manager).getSaslLoginConfigScope();
+            return new SCRAMServerSASL(scramType.getName(), scram, loginConfigScope, logger);
+         }
+      } catch (NoSuchAlgorithmException e) {
+         // can't be used then...
+      }
+      return null;
+   }
+
+   private static final class SCRAMServerSASL implements ServerSASL {
+
+      private final String name;
+      private final ScramServerFunctionality scram;
+      private SASLResult result;
+      private final String loginConfigScope;
+      private final Logger logger;
+
+      SCRAMServerSASL(String name, ScramServerFunctionality scram, String loginConfigScope, Logger logger) {
+         this.name = name;
+         this.scram = scram;
+         this.loginConfigScope = loginConfigScope;
+         this.logger = logger;
+      }
+
+      @Override
+      public String getName() {
+         return name;
+      }
+
+      @Override
+      public byte[] processSASL(byte[] bytes) {
+         String message = new String(bytes, StandardCharsets.US_ASCII);
+         try {
+            switch (scram.getState()) {
+               case INITIAL: {
+                  String userName = scram.handleClientFirstMessage(message);
+                  if (userName != null) {
+
+                     LoginContext loginContext = new LoginContext(loginConfigScope, new CallbackHandler() {
+
+                        @Override
+                        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                           for (Callback callback : callbacks) {
+                              if (callback instanceof NameCallback) {
+                                 ((NameCallback) callback).setName(userName);
+                              } else if (callback instanceof SCRAMMechanismCallback) {
+                                 ((SCRAMMechanismCallback) callback).setMechanism(name);
+                              } else if (callback instanceof DigestCallback) {
+                                 ((DigestCallback) callback).setDigest(scram.getDigest());
+                              } else if (callback instanceof HmacCallback) {
+                                 ((HmacCallback) callback).setHmac(scram.getHmac());
+                              } else {
+                                 throw new UnsupportedCallbackException(callback, "Unrecognized Callback " +
+                                          callback.getClass().getSimpleName());
+                              }
+                           }
+                        }
+                     });
+                     loginContext.login();

Review comment:
       Yes kerberos is the source for the roles. As mentioned above, there might be other sources as well but for the properties case its the properties file... One might even think about only having users in transport-phase and enhance with groups on application-phase then one needs to have a matching application-login-module also.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r600311748



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       I have added support for broker client sasl-scram now, this is also a test/validation for the SHA-512 method.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-795158598


   Any idea whats wrong with the J8 build? it complains about missing file but the j11+j14 do not complain...


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gtully commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gtully commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-801948778


   i built with jdk8 and did not see any problem


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r596995596



##########
File path: examples/protocols/amqp/sasl-scram/sasl-server/src/main/resources/artemis-users.properties
##########
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+test = ENC(VeEFPtxYIGIS0VA7e+W5+LpdLmazpcLH:4096:rIPD9cVvOoVJqzD7u4/qRMW1xGwILRG90g2OtWmn8T0=:7k8fGWO1zWPuZF0pzDCYnDCtmaJxLptqHS26SNsbGHU=)

Review comment:
       I wasnt suggesting people created it by hand. 
   
   Nothing anywhere, in this example, or docs, seems to tell people how to create these SCRAM-SHA specific contents, that was my point. Still seems to be the case.
   
   I havent used it but I know here is a user add command that does it and can do the masked stuff or not. I dont know how that works.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r603160840



##########
File path: artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java
##########
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.protocol.amqp.sasl.scram;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.qpid.proton.codec.DecodeException;

Review comment:
       Any suggestion would be welcome. The API just don't allow or declare any exceptions to be thrown. All current impl do not seem to have any problems as the are only have an initial response.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-785956722


   Okay it seems I'm using some jdk 11 features I'll adjust this.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601469379



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep;
+import org.apache.activemq.artemis.spi.core.security.scram.StringPrep.StringPrepError;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      if (user == null) {
+         userData = generateUserData(null); // generate random user data
+      } else {
+         String password = users.getProperty(user + SEPARATOR_MECHANISM + scram.name());
+         if (password == null) {
+            // fallback for probably unencoded user/password or a single encoded entry
+            password = users.getProperty(user);
+         }
+         if (PasswordMaskingUtil.isEncMasked(password)) {
+            String[] unwrap = PasswordMaskingUtil.unwrap(password).split(SEPARATOR_PARAMETER);

Review comment:
       Probably worth verifying this has the exact number of expected elements, to give a better failure if it doesnt?
   
   Comment trigged by memory of wondering how this stuff interacts with the the cli commands for adding users.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] laeubi commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
laeubi commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r591119286



##########
File path: tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/SaslScramTest.java
##########
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp.connect;

Review comment:
       SASL SCRAM should be transparent to proxies even though I don't know how "connect to another Artemis instance" is implemented. Anyways there is no requirement to only allow SASL-SCRAM, brokers can communicate using any other authentication mechnism if required.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on a change in pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on a change in pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#discussion_r601439473



##########
File path: artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/SCRAMPropertiesLoginModule.java
##########
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.spi.core.security.jaas;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.crypto.Mac;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
+import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
+import org.apache.activemq.artemis.spi.core.security.scram.UserData;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.jgroups.util.UUID;
+
+/**
+ * Login modules that uses properties files similar to the {@link PropertiesLoginModule}. It can
+ * either store the username-password in plain text or in an encrypted/hashed form. the
+ * {@link #main(String[])} method provides a way to prepare unencrypted data to be encrypted/hashed.
+ */
+public class SCRAMPropertiesLoginModule extends PropertiesLoader implements AuditLoginModule {
+
+   /**
+    *
+    */
+   private static final String SEPARATOR_MECHANISM = "|";
+   private static final String SEPARATOR_PARAMETER = ":";
+   private static final int MIN_ITERATIONS = 4096;
+   private static final SecureRandom RANDOM_GENERATOR = new SecureRandom();
+   private Subject subject;
+   private CallbackHandler callbackHandler;
+   private Properties users;
+   private Map<String, Set<String>> roles;
+   private UserData userData;
+   private String user;
+   private final Set<Principal> principals = new HashSet<>();
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                          Map<String, ?> options) {
+      this.subject = subject;
+      this.callbackHandler = callbackHandler;
+
+      init(options);
+      users = load(PropertiesLoginModule.USER_FILE_PROP_NAME, "user", options).getProps();
+      roles = load(PropertiesLoginModule.ROLE_FILE_PROP_NAME, "role", options).invertedPropertiesValuesMap();
+
+   }
+
+   @Override
+   public boolean login() throws LoginException {
+      NameCallback nameCallback = new NameCallback("Username: ");
+      executeCallbacks(nameCallback);
+      user = nameCallback.getName();
+      if (user == null) {
+         user = UUID.randomUUID().toString();
+      }
+      SCRAMMechanismCallback mechanismCallback = new SCRAMMechanismCallback();
+      executeCallbacks(mechanismCallback);
+      SCRAM scram = getTypeByString(mechanismCallback.getMechanism());
+      String password = users.getProperty(user, users.getProperty(user + SEPARATOR_MECHANISM + scram.name()));

Review comment:
       It seems more likely it should be be the one with the type at this point, given thats what the generator spits out, and what people should use unless they only want to support one mech or really like the plain text properties. Regardless, picking the more specific one seems the more obvious approach.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [activemq-artemis] gemmellr commented on pull request #3470: ARTEMIS-3106 - Support for SASL-SCRAM

Posted by GitBox <gi...@apache.org>.
gemmellr commented on pull request #3470:
URL: https://github.com/apache/activemq-artemis/pull/3470#issuecomment-806701276


   > But whats the value in removing it? It does not simplify the code, it is not enabled by default (so peopel can choose if they want to enable it or not) and it does not remove complexity as it is just another set of algorithms. On the other hand, adding it "later" or let people "just plug in their own support for it" seems way much more effort on the long run. For example the client-side is currently not pluggable.
   
   I wouldnt recommend anyone embark on SCRAM-SHA-1 usage at this point, and folks have managed without it in Artemis for all this time. As such it simply seems sensible to at least consider ommitting it and simplifying things rather than adding it at this stage in its life. The 'it can be added later' was merely a note that its possible, I wouldnt really  expect it to be if omitted. However trivial, not adding such things just means less code to maintain, less options to document (not that any of this is documented yet), and avoids the need to consider/discuss dropping them at some point.
   
   The client side isnt pluggable currently thats true, but could be made so (not saying now, but some point). That would seem a better addition at some point rather than SCRAM-SHA-1 support. As you pointed out yourself when arguing agaisnt need for the client bits, brokers can offer other mechanisms, so the lack of an old mech there doesnt seem like it would be a significant problem when it supports the newer ones.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org