Github user gemmellr commented on a diff in the pull request: https://github.com/apache/qpid-jms/pull/10#discussion_r128754495 --- Diff: qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java --- @@ -495,6 +512,169 @@ public void run() } } + public void expectGSSAPIFail(Symbol mech) throws Exception { + SaslMechanismsFrame saslMechanismsFrame = new SaslMechanismsFrame().setSaslServerMechanisms(mech); + + addHandler(new HeaderHandlerImpl(AmqpHeader.SASL_HEADER, AmqpHeader.SASL_HEADER, + new FrameSender( + this, FrameType.SASL, 0, + saslMechanismsFrame, null))); + + addHandler(new SaslInitMatcher().withMechanism(equalTo(mech))); + + } + + public void expectGSSAPI(Symbol mech, String serviceName) throws Exception { + + SaslMechanismsFrame saslMechanismsFrame = new SaslMechanismsFrame().setSaslServerMechanisms(mech); + + addHandler(new HeaderHandlerImpl(AmqpHeader.SASL_HEADER, AmqpHeader.SASL_HEADER, + new FrameSender( + this, FrameType.SASL, 0, + saslMechanismsFrame, null))); + + // setup server gss context + LoginContext loginContext = new LoginContext("", null, null, + kerb5InlineConfig(serviceName, false)); + loginContext.login(); + final Subject serverSubject =loginContext.getSubject(); + + LOGGER.info("saslServer subject:" + serverSubject.getPrivateCredentials()); + + Map<String, ?> config = new HashMap(); + final CallbackHandler handler = new CallbackHandler() { + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + LOGGER.info("Here with: " + Arrays.asList(callbacks)); + for (Callback callback :callbacks) { + if (callback instanceof AuthorizeCallback) { + AuthorizeCallback authorizeCallback = (AuthorizeCallback) callback; + authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals(authorizeCallback.getAuthorizationID())); + } + } + } + }; + final SaslServer saslServer = Subject.doAs(serverSubject, new PrivilegedExceptionAction<SaslServer>() { + @Override + public SaslServer run() throws Exception { + return Sasl.createSaslServer(mech.toString(), null, null, config, handler); + } + }); + + final SaslChallengeFrame challengeFrame = new SaslChallengeFrame(); + + SaslInitMatcher saslInitMatcher = new SaslInitMatcher() + .withMechanism(equalTo(mech)) + .withInitialResponse(new BaseMatcher<Binary>() { + + @Override + public void describeTo(Description description) {} + + @Override + public boolean matches(Object o) { + if (o == null) { + LOGGER.error("Got null initial response!"); + return false; + } + final Binary binary = (Binary) o; + // validate via sasl + byte[] token = null; + try { + token = Subject.doAs(serverSubject, new PrivilegedExceptionAction<byte[]>() { + @Override + public byte[] run() throws Exception { + LOGGER.info("Evaluate Response.. size:" + binary.getLength()); + return saslServer.evaluateResponse(binary.getArray()); + } + }); + } catch (PrivilegedActionException e) { + e.printStackTrace(); + } + LOGGER.info("Complete:" + saslServer.isComplete()); + + if (token != null) { + // fling it back in on complete + challengeFrame.setChallenge(new Binary(token)); + } + return true; + } + }).onCompletion(new AmqpPeerRunnable() { + @Override + public void run() { + TestAmqpPeer.this.sendFrame( + FrameType.SASL, 0, + challengeFrame, + null, + false, 0); + } + }); + + AtomicBoolean response = new AtomicBoolean(false); + SaslResponseMatcher challengeMatcher = new SaslResponseMatcher().withResponse(new BaseMatcher<Binary>() { + + @Override + public void describeTo(Description description) {} + + @Override + public boolean matches(Object o) { + final Binary binary = (Binary) o; + if (!saslServer.isComplete()) { + // validate via sasl + byte[] token = null; + try { + token = Subject.doAs(serverSubject, new PrivilegedExceptionAction<byte[]>() { + @Override + public byte[] run() throws Exception { + LOGGER.info("Evaluate challenge response.. size:" + binary.getLength()); + return saslServer.evaluateResponse(binary.getArray()); + } + }); + } catch (PrivilegedActionException e) { + e.printStackTrace(); + } + LOGGER.info("Complete:" + saslServer.isComplete()); + if (token != null) { + // fling it back + challengeFrame.setChallenge(new Binary(token)); + response.set(true); + } + return true; + } + + return false; + } + }).onCompletion(new AmqpPeerRunnable() { + @Override + public void run() { + if (response.get()) { + TestAmqpPeer.this.sendFrame( + FrameType.SASL, 0, + challengeFrame, + null, + false, 0); + } + + if (saslServer.isComplete()) { --- End diff -- This bit seems off, we shouldn't really be sending a challenge and an outcome frames at the same time, and in particular changes coming in proton-j 0.20.0 to allow accessing the 'additional-data' in the outcome may mean only one might be seen by the recipient. Either its really challenge, in which case we expect a response (which can just be empty), or we class it as 'additional-data' and send it as part of the outcome frame (when it is a successful outcome, only).
--- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastruct...@apache.org or file a JIRA ticket with INFRA. --- --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org For additional commands, e-mail: dev-h...@qpid.apache.org