+ if (!authorizationIdFromClient.isEmpty() && !authorizationIdFromClient.equals(username))
+ throw new SaslAuthenticationException("Authentication failed: Client requested an authorization id that is different from username");
+
+ this.authorizationId = username;
+
+ complete = true;
+ return new byte[0];
+ }
+
+ private List<String> extractTokens(String string) {
+ List<String> tokens = new ArrayList<>();
+ int startIndex = 0;
+ for (int i = 0; i < 4; ++i) {
+ int endIndex = string.indexOf("\u0000", startIndex);
+ if (endIndex == -1) {
+ tokens.add(string.substring(startIndex));
+ break;
+ }
+ tokens.add(string.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+
+ if (tokens.size() != 3)
+ throw new SaslAuthenticationException("Invalid SASL/PLAIN response: expected 3 tokens, got " +
+ tokens.size());
+
+ return tokens;
+ }
+
+ @Override
+ public String getAuthorizationID() {
+ if (!complete)
+ throw new IllegalStateException("Authentication exchange has not completed");
+ return authorizationId;
+ }
+
+ @Override
+ public String getMechanismName() {
+ return PLAIN_MECHANISM;
+ }
+
+ @Override
+ public Object getNegotiatedProperty(String propName) {
+ if (!complete)
+ throw new IllegalStateException("Authentication exchange has not completed");
+ return null;
+ }
+
+ @Override
+ public boolean isComplete() {
+ return complete;
+ }
+
+ @Override
+ public byte[] unwrap(byte[] incoming, int offset, int len) {
+ if (!complete)
+ throw new IllegalStateException("Authentication exchange has not completed");
+ return Arrays.copyOfRange(incoming, offset, offset + len);
+ }
+
+ @Override
+ public byte[] wrap(byte[] outgoing, int offset, int len) {
+ if (!complete)
+ throw new IllegalStateException("Authentication exchange has not completed");
+ return Arrays.copyOfRange(outgoing, offset, offset + len);
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ public static class PlainSaslServerFactory1 implements SaslServerFactory {
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map<String, ?> props, CallbackHandler cbh)
+ throws SaslException {
+
+ if (!PLAIN_MECHANISM.equals(mechanism))
+ throw new SaslException(String.format("Mechanism \'%s\' is not supported. Only PLAIN is supported.", mechanism));
+
+ return new PlainSaslServer1();
+ }
+
+ @Override
+ public String[] getMechanismNames(Map<String, ?> props) {
+ if (props == null) return new String[]{PLAIN_MECHANISM};
+ String noPlainText = (String) props.get(Sasl.POLICY_NOPLAINTEXT);
+ if ("true".equals(noPlainText))
+ return new String[]{};
+ else
+ return new String[]{PLAIN_MECHANISM};
+ }
+ }