Skip to content

Commit

Permalink
Use RedisCredentials with HELLO command
Browse files Browse the repository at this point in the history
  • Loading branch information
sazzad16 committed Aug 19, 2023
1 parent 2c609cf commit 86e3262
Showing 1 changed file with 72 additions and 63 deletions.
135 changes: 72 additions & 63 deletions src/main/java/redis/clients/jedis/Connection.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package redis.clients.jedis;

import static redis.clients.jedis.util.SafeEncoder.encode;

import java.io.Closeable;
import java.io.IOException;
import java.net.Socket;
Expand All @@ -9,7 +11,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

import redis.clients.jedis.Protocol.Command;
Expand All @@ -25,7 +27,6 @@
import redis.clients.jedis.util.JedisMetaInfo;
import redis.clients.jedis.util.RedisInputStream;
import redis.clients.jedis.util.RedisOutputStream;
import redis.clients.jedis.util.SafeEncoder;

public class Connection implements Closeable {

Expand Down Expand Up @@ -270,14 +271,14 @@ public String getStatusCodeReply() {
if (null == resp) {
return null;
} else {
return SafeEncoder.encode(resp);
return encode(resp);
}
}

public String getBulkReply() {
final byte[] result = getBinaryBulkReply();
if (null != result) {
return SafeEncoder.encode(result);
return encode(result);
} else {
return null;
}
Expand Down Expand Up @@ -391,44 +392,37 @@ private static boolean validateClientInfo(String info) {
private void initializeFromClientConfig(JedisClientConfig config) {
try {
connect();
protocol = config.getRedisProtocol();

boolean doClientName = true;

/// HELLO and AUTH -->
if (protocol == RedisProtocol.RESP3 && config.getUser() != null) {
protocol = config.getRedisProtocol();

hello(protocol, config.getUser(), config.getPassword(), config.getClientName());
doClientName = false;
AtomicBoolean clientNamePending = new AtomicBoolean(false);
String clientName = config.getClientName();
if (clientName != null){
validateClientInfo(clientName);
clientNamePending.set(true);
}

} else {
Supplier<RedisCredentials> credentialsProvider = config.getCredentialsProvider();
if (credentialsProvider instanceof RedisCredentialsProvider) {

Supplier<RedisCredentials> credentialsProvider = config.getCredentialsProvider();
if (credentialsProvider instanceof RedisCredentialsProvider) {
try {
((RedisCredentialsProvider) credentialsProvider).prepare();
auth(credentialsProvider);
} finally {
((RedisCredentialsProvider) credentialsProvider).cleanUp();
}
} else {
auth(credentialsProvider);
try {
((RedisCredentialsProvider) credentialsProvider).prepare();
helloOrAuth(protocol, credentialsProvider.get(), clientName, clientNamePending);
} finally {
((RedisCredentialsProvider) credentialsProvider).cleanUp();
}
} else if (credentialsProvider != null) {

if (protocol != null) {
hello(protocol);
}
}
helloOrAuth(protocol, credentialsProvider.get(), clientName, clientNamePending);
} else {

int dbIndex = config.getDatabase();
if (dbIndex > 0) {
select(dbIndex);
helloOrAuth(protocol, new DefaultRedisCredentials(config.getUser(), config.getPassword()),
clientName, clientNamePending);
}

List<CommandArguments> fireAndForgetMsg = new ArrayList<>();

String clientName = config.getClientName();
if (doClientName && clientName != null && validateClientInfo(clientName)) {
if (clientNamePending.get()) {
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETNAME).add(clientName));
}

Expand All @@ -448,6 +442,12 @@ private void initializeFromClientConfig(JedisClientConfig config) {
sendCommand(arg);
}
getMany(fireAndForgetMsg.size());

int dbIndex = config.getDatabase();
if (dbIndex > 0) {
select(dbIndex);
}

} catch (JedisException je) {
try {
disconnect();
Expand All @@ -458,49 +458,58 @@ private void initializeFromClientConfig(JedisClientConfig config) {
}
}

private Map hello(final RedisProtocol protocol) {
sendCommand(Protocol.Command.HELLO, String.valueOf(protocol.version()));
Map reply = BuilderFactory.ENCODED_OBJECT_MAP.build(getOne());
// LoggerFactory.getLogger(Connection.class).info("HELLO reply: {}", reply);
return reply;
}

private Map hello(final RedisProtocol protocol, final String user, final String password,
final String clientName) {
if (clientName == null) {
sendCommand(Protocol.Command.HELLO, String.valueOf(protocol.version()),
Protocol.Keyword.AUTH.name(), user, password);
} else {
sendCommand(Protocol.Command.HELLO, String.valueOf(protocol.version()),
Protocol.Keyword.AUTH.name(), user, password,
Protocol.Keyword.SETNAME.name(), clientName);
private void helloOrAuth(final RedisProtocol protocol, final RedisCredentials credentials,
final String clientName, final AtomicBoolean clientNamePending) {
if (credentials == null || credentials.getPassword() == null) {
if (protocol != null) {
sendCommand(Protocol.Command.HELLO, encode(protocol.version()));
getOne();
}
return;
}
Map reply = BuilderFactory.ENCODED_OBJECT_MAP.build(getOne());
// LoggerFactory.getLogger(Connection.class).info("HELLO reply: {}", reply);
return reply;
}

private void auth(final Supplier<RedisCredentials> credentialsProvider) {
RedisCredentials credentials = credentialsProvider.get();
if (credentials == null || credentials.getPassword() == null) return;

// Source: https://stackoverflow.com/a/9670279/4021802
ByteBuffer passBuf = Protocol.CHARSET.encode(CharBuffer.wrap(credentials.getPassword()));
byte[] rawPass = Arrays.copyOfRange(passBuf.array(), passBuf.position(), passBuf.limit());
Arrays.fill(passBuf.array(), (byte) 0); // clear sensitive data

if (credentials.getUser() != null) {
sendCommand(Protocol.Command.AUTH, SafeEncoder.encode(credentials.getUser()), rawPass);
} else {
sendCommand(Protocol.Command.AUTH, rawPass);
}
try {
/// actual HELLO or AUTH -->
if (protocol != null) {
if (credentials.getUser() != null) {
if (clientName != null) {
sendCommand(Protocol.Command.HELLO, encode(protocol.version()),
Protocol.Keyword.AUTH.getRaw(), encode(credentials.getUser()), rawPass,
Protocol.Keyword.SETNAME.getRaw(), encode(clientName));
} else {
sendCommand(Protocol.Command.HELLO, encode(protocol.version()),
Protocol.Keyword.AUTH.getRaw(), encode(credentials.getUser()), rawPass);
}
getOne();
clientNamePending.set(false);
} else { // getUser() == null
sendCommand(Protocol.Command.HELLO, encode(protocol.version()));
getOne();
sendCommand(Protocol.Command.AUTH, rawPass);
getOne();
}
} else { // protocol == null
if (credentials.getUser() != null) {
sendCommand(Protocol.Command.AUTH, encode(credentials.getUser()), rawPass);
} else {
sendCommand(Protocol.Command.AUTH, rawPass);
}
getStatusCodeReply(); // OK
// setnamePending unchanged
}
/// <-- actual HELLO or AUTH
} finally {

Arrays.fill(rawPass, (byte) 0); // clear sensitive data
Arrays.fill(rawPass, (byte) 0); // clear sensitive data
}

// clearing 'char[] credentials.getPassword()' should be
// handled in RedisCredentialsProvider.cleanUp()

getStatusCodeReply(); // OK
}

public String select(final int index) {
Expand Down

0 comments on commit 86e3262

Please sign in to comment.