use of org.voltcore.utils.ssl.MessagingChannel in project voltdb by VoltDB.
the class ConnectionUtil method getAuthenticatedConnection.
private static Object[] getAuthenticatedConnection(String service, InetSocketAddress addr, String username, byte[] hashedPassword, final Subject subject, ClientAuthScheme scheme, SSLEngine sslEngine) throws IOException {
Object[] returnArray = new Object[3];
boolean success = false;
if (addr.isUnresolved()) {
throw new java.net.UnknownHostException(addr.getHostName());
}
SocketChannel aChannel = SocketChannel.open(addr);
returnArray[0] = aChannel;
assert (aChannel.isConnected());
if (!aChannel.isConnected()) {
// TODO Can open() be asynchronous if configureBlocking(true)?
throw new IOException("Failed to open host " + ReverseDNSCache.hostnameOrAddress(addr.getAddress()));
}
synchronized (aChannel.blockingLock()) {
aChannel.configureBlocking(false);
aChannel.socket().setTcpNoDelay(true);
}
if (sslEngine != null) {
TLSHandshaker handshaker = new TLSHandshaker(aChannel, sslEngine);
boolean shookHands = false;
try {
shookHands = handshaker.handshake();
} catch (IOException e) {
aChannel.close();
throw new IOException("SSL handshake failed", e);
}
if (!shookHands) {
aChannel.close();
throw new IOException("SSL handshake failed");
}
}
final long[] retvals = new long[4];
returnArray[1] = retvals;
MessagingChannel messagingChannel = MessagingChannel.get(aChannel, sslEngine);
try {
/*
* Send login info
*/
synchronized (aChannel.blockingLock()) {
aChannel.configureBlocking(true);
aChannel.socket().setTcpNoDelay(true);
}
// encode strings
byte[] serviceBytes = service == null ? null : service.getBytes(Constants.UTF8ENCODING);
byte[] usernameBytes = username == null ? null : username.getBytes(Constants.UTF8ENCODING);
// get the length of the data to serialize
int requestSize = 4;
//version and scheme
requestSize += 2;
requestSize += serviceBytes == null ? 4 : 4 + serviceBytes.length;
requestSize += usernameBytes == null ? 4 : 4 + usernameBytes.length;
requestSize += hashedPassword.length;
ByteBuffer b = ByteBuffer.allocate(requestSize);
// serialize it
// length prefix
b.putInt(requestSize - 4);
// version
b.put((byte) 1);
b.put((byte) scheme.getValue());
// data service (export|database)
SerializationHelper.writeVarbinary(serviceBytes, b);
SerializationHelper.writeVarbinary(usernameBytes, b);
b.put(hashedPassword);
b.flip();
try {
messagingChannel.writeMessage(b);
} catch (IOException e) {
throw new IOException("Failed to write authentication message to server.", e);
}
if (b.hasRemaining()) {
throw new IOException("Failed to write authentication message to server.");
}
ByteBuffer loginResponse;
try {
loginResponse = messagingChannel.readMessage();
} catch (IOException e) {
throw new IOException("Authentication rejected", e);
}
byte version = loginResponse.get();
byte loginResponseCode = loginResponse.get();
if (version == Constants.AUTH_HANDSHAKE_VERSION) {
byte tag = loginResponseCode;
if (subject == null) {
aChannel.close();
throw new IOException("Server requires an authenticated JAAS principal");
}
if (tag != Constants.AUTH_SERVICE_NAME) {
aChannel.close();
throw new IOException("Wire protocol format violation error");
}
String servicePrincipal = SerializationHelper.getString(loginResponse);
loginResponse = performAuthenticationHandShake(aChannel, subject, servicePrincipal);
loginResponseCode = loginResponse.get();
}
if (loginResponseCode != 0) {
aChannel.close();
switch(loginResponseCode) {
case Constants.MAX_CONNECTIONS_LIMIT_ERROR:
throw new IOException("Server has too many connections");
case Constants.WIRE_PROTOCOL_TIMEOUT_ERROR:
throw new IOException("Connection timed out during authentication. " + "The VoltDB server may be overloaded.");
case Constants.EXPORT_DISABLED_REJECTION:
throw new IOException("Export not enabled for server");
case Constants.WIRE_PROTOCOL_FORMAT_ERROR:
throw new IOException("Wire protocol format violation error");
case Constants.AUTHENTICATION_FAILURE_DUE_TO_REJOIN:
throw new IOException("Failed to authenticate to rejoining node");
default:
throw new IOException("Authentication rejected");
}
}
retvals[0] = loginResponse.getInt();
retvals[1] = loginResponse.getLong();
retvals[2] = loginResponse.getLong();
retvals[3] = loginResponse.getInt();
int buildStringLength = loginResponse.getInt();
byte[] buildStringBytes = new byte[buildStringLength];
loginResponse.get(buildStringBytes);
returnArray[2] = new String(buildStringBytes, Constants.UTF8ENCODING);
synchronized (aChannel.blockingLock()) {
aChannel.configureBlocking(false);
aChannel.socket().setKeepAlive(true);
}
success = true;
} finally {
messagingChannel.cleanUp();
if (!success) {
aChannel.close();
}
}
return returnArray;
}
Aggregations