ScramInitialClientMessage(final ScramClient scramClient, final String authenticationName, final boolean binding, final byte[] nonce, final int initialPartIndex, final byte[] messageBytes) { this.binding = binding; this.initialPartIndex = initialPartIndex; bindingType = scramClient.getBindingType(); bindingData = scramClient.getRawBindingData(); mechanism = scramClient.getMechanism(); authorizationId = scramClient.getAuthorizationId(); this.authenticationName = authenticationName; this.nonce = nonce; this.messageBytes = messageBytes; }
public ScramMechanism getMechanism() { return initialResponse.getMechanism(); }
public static ScramServerErrorCode fromErrorString(String value) { try { return valueOf(value.replace('-', '_').toUpperCase(Locale.US)); } catch (IllegalArgumentException ignored) { return OTHER_ERROR; } }
if (initialResponse.getMechanism() != mechanism) { throw saslScram.mechUnmatchedMechanism(mechanism.toString(), initialResponse.getMechanism().toString()); if (initialChallenge.getMechanism() != mechanism) { throw saslScram.mechUnmatchedMechanism(mechanism.toString(), initialChallenge.getMechanism().toString()); final boolean plus = mechanism.isPlus(); if (getAuthorizationId() != null) { b2.append("a="); StringPrep.encode(getAuthorizationId(), b2, StringPrep.PROFILE_SASL_STORED | StringPrep.MAP_SCRAM_LOGIN_CHARS); b2.append('n'); b2.append(','); if (getAuthorizationId() != null) { b2.append("a="); StringPrep.encode(getAuthorizationId(), b2, StringPrep.PROFILE_SASL_STORED | StringPrep.MAP_SCRAM_LOGIN_CHARS); encoded.append(',').append('r').append('=').append(initialResponse.getRawNonce()).append(initialChallenge.getRawServerNonce()); initialChallenge.getIterationCount(), initialChallenge.getRawSalt() ); ScramDigestPassword password = MechanismUtil.getPasswordCredential( initialResponse.getAuthenticationName(), callbackHandler, ScramDigestPassword.class, mechanism.getPasswordAlgorithm(), parameters,
if (clientMessage.getMechanism() != mechanism) { throw saslScram.mechUnmatchedMechanism(mechanism.toString(), clientMessage.getMechanism().toString()); final Mac mac = Mac.getInstance(getMechanism().getHmacName()); final MessageDigest messageDigest = MessageDigest.getInstance(getMechanism().getMessageDigestName()); byte[] saltedPassword = initialResult.getScramDigestPassword().getDigest(); mac.init(new SecretKeySpec(saltedPassword, mac.getAlgorithm())); mac.update(ScramUtil.CLIENT_KEY_BYTES); final byte[] clientFirstMessage = clientMessage.getInitialResponse().getRawMessageBytes(); final int clientFirstMessageBareStart = clientMessage.getInitialResponse().getInitialPartIndex(); mac.update(clientFirstMessage, clientFirstMessageBareStart, clientFirstMessage.length - clientFirstMessageBareStart); if(trace) saslScram.tracef("[S] Using client first message: %s%n", ByteIterator.ofBytes(copyOfRange(clientFirstMessage, clientFirstMessageBareStart, clientFirstMessage.length)).hexEncode().drainToString()); mac.update((byte) ','); final byte[] serverFirstMessage = initialResult.getScramInitialChallenge().getRawMessageBytes(); mac.update(serverFirstMessage); if(trace) saslScram.tracef("[S] Using server first message: %s%n", ByteIterator.ofBytes(serverFirstMessage).hexEncode().drainToString()); mac.update((byte) ','); final byte[] response = clientMessage.getRawMessageBytes(); final int proofOffset = clientMessage.getProofOffset(); mac.update(response, 0, proofOffset); // client-final-message-without-proof if(trace) saslScram.tracef("[S] Using client final message without proof: %s%n", ByteIterator.ofBytes(copyOfRange(response, 0, proofOffset)).hexEncode().drainToString()); final byte[] recoveredClientProof = clientMessage.getRawClientProof(); if(trace) saslScram.tracef("[S] Client proof: %s%n", ByteIterator.ofBytes(recoveredClientProof).hexEncode().drainToString()); ScramUtil.xor(recoveredClientKey, recoveredClientProof); if(trace) saslScram.tracef("[S] Recovered client key: %s%n", ByteIterator.ofBytes(recoveredClientKey).hexEncode().drainToString());
public ScramFinalClientMessage parseFinalClientMessage(final ScramInitialClientMessage initialResponse, final ScramInitialServerResult initialResult, final byte[] bytes) throws AuthenticationMechanismException { final ScramInitialServerMessage initialChallenge = initialResult.getScramInitialChallenge(); Assert.checkNotNullParam("initialResponse", initialResponse); Assert.checkNotNullParam("initialChallenge", initialChallenge); final ScramMechanism mechanism = initialResponse.getMechanism(); if (mechanism != initialChallenge.getMechanism()) { throw saslScram.mechUnmatchedMechanism(mechanism.toString(), initialChallenge.getMechanism().toString()); final String bindingType = initialResponse.getBindingType(); final byte[] bindingData = initialResponse.getRawBindingData(); final boolean binding = initialResponse.isBinding(); if (cbindFlag == 'p') { if (! binding) { throw new ScramServerException(saslScram.mechChannelBindingNotSupported(), ScramServerErrorCode.CHANNEL_BINDING_NOT_SUPPORTED); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.CHANNEL_BINDING_NOT_PROVIDED); throw new ScramServerException(saslScram.mechChannelBindingTypeMismatch(), ScramServerErrorCode.UNSUPPORTED_CHANNEL_BINDING_TYPE); if (mechanism.isPlus()) { throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); if (mechanism.isPlus()) { throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); if (! authorizationID.equals(initialResponse.getAuthorizationId())) {
throw saslScram.mechClientRefusesToInitiateAuthentication().toSaslException(); final ScramInitialClientMessage initialClientMessage = scramServer.parseInitialClientMessage(bindingCallback, response); final ScramInitialServerResult initialServerResult = scramServer.evaluateInitialResponse(initialClientMessage); this.initialClientMessage = initialClientMessage; this.initialServerResult = initialServerResult; final String authorizationId = initialClientMessage.getAuthorizationId(); this.authorizationId = authorizationId == null ? initialClientMessage.getAuthenticationName() : authorizationId; setNegotiationState(S_FINAL_MESSAGE); ok = true; return initialServerResult.getScramInitialChallenge().getMessageBytes(); final ScramFinalClientMessage finalClientMessage = scramServer.parseFinalClientMessage(initialClientMessage, initialServerResult, response); final ScramFinalServerMessage finalServerMessage = scramServer.evaluateFinalClientMessage(initialServerResult, finalClientMessage); setNegotiationState(COMPLETE_STATE); ok = true; return finalServerMessage.getMessageBytes(); setNegotiationState(FAILED_STATE); if (saslScram.isDebugEnabled()) { saslScram.debugf(cause, "[%s] error when evaluating message from client during state [%s]: %s", getMechanismName(), state, cause.getError().getText()); return cause.getError().getMessageBytes(); } catch (AuthenticationMechanismException e) { throw e.toSaslException();
final Mac mac = Mac.getInstance(getMechanism().getHmacName()); ScramDigestPassword password = finalResponse.getPassword(); mac.init(new SecretKeySpec(password.getDigest(), mac.getAlgorithm())); byte[] serverKey = mac.doFinal(ScramUtil.SERVER_KEY_BYTES); if(trace) saslScram.tracef("[C] Server key: %s%n", ByteIterator.ofBytes(serverKey).hexEncode().drainToString()); mac.init(new SecretKeySpec(serverKey, mac.getAlgorithm())); byte[] clientFirstMessage = finalResponse.getInitialResponse().getRawMessageBytes(); int bareStart = finalResponse.getInitialResponse().getInitialPartIndex(); mac.update(clientFirstMessage, bareStart, clientFirstMessage.length - bareStart); mac.update((byte) ','); byte[] serverFirstMessage = finalResponse.getInitialChallenge().getRawMessageBytes(); mac.update(serverFirstMessage); mac.update((byte) ','); byte[] clientFinalMessage = finalResponse.getRawMessageBytes(); mac.update(clientFinalMessage, 0, finalResponse.getProofOffset()); byte[] serverSignature = mac.doFinal(); if(trace) saslScram.tracef("[C] Recovered server signature: %s%n", ByteIterator.ofBytes(serverSignature).hexEncode().drainToString()); if (! Arrays.equals(finalChallenge.getRawServerSignature(), serverSignature)) { throw saslScram.mechServerAuthenticityCannotBeVerified();
public ScramInitialServerResult evaluateInitialResponse(final ScramInitialClientMessage clientMessage) throws AuthenticationMechanismException { final boolean trace = saslScram.isTraceEnabled(); if (clientMessage.getMechanism() != mechanism) { throw saslScram.mechUnmatchedMechanism(mechanism.toString(), clientMessage.getMechanism().toString()); final NameCallback nameCallback = new NameCallback("Remote authentication name", clientMessage.getAuthenticationName()); max(minimumIterationCount, min(maximumIterationCount, ScramDigestPassword.DEFAULT_ITERATION_COUNT)) ); final ScramDigestPassword password = MechanismUtil.getPasswordCredential(clientMessage.getAuthenticationName(), callbackHandler, ScramDigestPassword.class, mechanism.getPasswordAlgorithm(), null, generateParameters, providers, saslScram); b.append(clientMessage.getRawNonce()); final byte[] serverNonce = ScramUtil.generateNonce(28, getRandom()); b.append(serverNonce); b.append(','); return new ScramInitialServerResult(new ScramInitialServerMessage(clientMessage, serverNonce, salt, iterationCount, messageBytes), password);
this.initialResponse = scramClient.getInitialResponse(); setNegotiationState(ST_R1_SENT); ok = true; return initialResponse.getMessageBytes(); final ScramInitialServerMessage initialChallenge = scramClient.parseInitialServerMessage(initialResponse, challenge); this.finalResponse = scramClient.handleInitialChallenge(initialResponse, initialChallenge); setNegotiationState(ST_R2_SENT); ok = true; return finalResponse.getMessageBytes(); final ScramFinalServerMessage finalChallenge = scramClient.parseFinalServerMessage(challenge); scramClient.verifyFinalChallenge(finalResponse, finalChallenge); setNegotiationState(COMPLETE_STATE); ok = true;
if (bindingData != null) { binding = true; if (mechanism.isPlus()) { encoded.append("p="); encoded.append(bindingType); StringPrep.encode(name, encoded, StringPrep.PROFILE_SASL_STORED | StringPrep.MAP_SCRAM_LOGIN_CHARS); encoded.append(',').append('r').append('='); final byte[] nonce = ScramUtil.generateNonce(48, getRandom()); encoded.append(nonce); return new ScramInitialClientMessage(this, name, binding, nonce, initialPartIndex, encoded.toArray());
bi.next(); if (bi.next() == '=') { throw saslScram.scramServerRejectedAuthentication(ScramServerErrorCode.fromErrorString(bi.delimitedBy(',').asUtf8String().drainToString())); throw saslScram.mechInvalidMessageReceived(); final byte[] clientNonce = initialResponse.getRawNonce(); if (! bi.limitedTo(clientNonce.length).contentEquals(ByteIterator.ofBytes(clientNonce))) { throw saslScram.mechNoncesDoNotMatch(); throw saslScram.mechInvalidMessageReceived(); iterationCount = ScramUtil.parsePosInt(bi); if (iterationCount < minimumIterationCount) { throw saslScram.mechIterationCountIsTooLow(iterationCount, minimumIterationCount); throw saslScram.mechInvalidMessageReceived(); return new ScramInitialServerMessage(initialResponse, serverNonce, salt, iterationCount, challenge);
if (! mechanism.isPlus()) { throw new ScramServerException(saslScram.mechChannelBindingNotSupported(), ScramServerErrorCode.SERVER_DOES_NOT_SUPPORT_CHANNEL_BINDING); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.CHANNEL_BINDING_NOT_PROVIDED); throw new ScramServerException(saslScram.mechChannelBindingTypeMismatch(), ScramServerErrorCode.UNSUPPORTED_CHANNEL_BINDING_TYPE); if (mechanism.isPlus()) { throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); if (mechanism.isPlus()) { throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); throw new ScramServerException(saslScram.mechChannelBindingNotProvided(), ScramServerErrorCode.SERVER_DOES_SUPPORT_CHANNEL_BINDING); return new ScramInitialClientMessage(mechanism, authorizationID, authenticationName, binding, bindingType, bindingData, nonce, initialPartIndex, response); } catch (NoSuchElementException ignored) { throw saslScram.mechInvalidMessageReceived();
@Override public final ScramServerException scramServerRejectedAuthentication(final ScramServerErrorCode errorCode) { final ScramServerException result = new ScramServerException(String.format(getLoggingLocale(), scramServerRejectedAuthentication$str()), errorCode); final StackTraceElement[] st = result.getStackTrace(); result.setStackTrace(Arrays.copyOfRange(st, 1, st.length)); return result; } private static final String mechInvalidOTPPasswordFormatType = "ELY05167: Invalid OTP password format type";
public ScramFinalServerMessage parseFinalServerMessage(final byte[] messageBytes) throws AuthenticationMechanismException { final ByteIterator bi = ByteIterator.ofBytes(messageBytes); final byte[] sig; try { int c = bi.next(); if (c == 'e') { if (bi.next() == '=') { throw saslScram.scramServerRejectedAuthentication(ScramServerErrorCode.fromErrorString(bi.delimitedBy(',').asUtf8String().drainToString())); } throw saslScram.mechInvalidMessageReceived(); } else if (c == 'v' && bi.next() == '=') { sig = bi.delimitedBy(',').asUtf8String().base64Decode().drain(); } else { throw saslScram.mechInvalidMessageReceived(); } if (bi.hasNext()) { throw saslScram.mechInvalidMessageReceived(); } } catch (IllegalArgumentException e) { throw saslScram.mechInvalidMessageReceived(); } return new ScramFinalServerMessage(sig, messageBytes); }
public ScramServer createServer(final CallbackHandler callbackHandler, final SecureRandom random, final ChannelBindingCallback bindingCallback, final int minimumIterationCount, final int maximumIterationCount, final Supplier<Provider[]> providers) throws AuthenticationMechanismException { final byte[] bindingData; final String bindingType; if (bindingCallback != null) { bindingData = bindingCallback.getBindingData(); bindingType = bindingCallback.getBindingType(); } else { if (plus) return null; bindingData = null; bindingType = null; } return new ScramServer(this, callbackHandler, random, bindingData, bindingType, minimumIterationCount, maximumIterationCount, providers); }
/** * Create a SCRAM client for this mechanism. * * @param authorizationId the authorization ID ({@code null} if none is given) * @param callbackHandler the callback handler (may not be {@code null}) * @param secureRandom an optional secure random implementation to use (may be {@code null}) * @param bindingCallback the optional channel binding callback result (may be {@code null}) * @param minimumIterationCount the minimum iteration count to allow * @param maximumIterationCount the maximum iteration count to allow * @return the SCRAM client, or {@code null} if the client cannot be created from this mechanism variant * @throws AuthenticationMechanismException if the mechanism fails for some reason * @see WildFlySasl#SCRAM_MIN_ITERATION_COUNT * @see WildFlySasl#SCRAM_MAX_ITERATION_COUNT */ public ScramClient createClient(final String authorizationId, final CallbackHandler callbackHandler, final SecureRandom secureRandom, final ChannelBindingCallback bindingCallback, final int minimumIterationCount, final int maximumIterationCount, final Supplier<Provider[]> providers) throws AuthenticationMechanismException { final byte[] bindingData; final String bindingType; if (bindingCallback != null) { bindingData = bindingCallback.getBindingData(); bindingType = bindingCallback.getBindingType(); } else { if (plus) return null; bindingData = null; bindingType = null; } return new ScramClient(this, authorizationId, callbackHandler, secureRandom, bindingData, bindingType, minimumIterationCount, maximumIterationCount, providers); }
ScramServerErrorCode() { text = name().replace('_', '-').toLowerCase(Locale.US); final int length = text.length(); byte[] msg = new byte[length + 2]; msg[0] = 'e'; msg[1] = '='; System.arraycopy(text.getBytes(StandardCharsets.UTF_8), 0, msg, 2, length); messageBytes = msg; }
public String getMessage() { return super.getMessage() + ": " + error.getText(); }
public ScramMechanism getMechanism() { return initialResponse.getMechanism(); }