This commit is contained in:
Clebert Suconic 2018-06-04 12:01:02 -04:00
commit 655f1dc46a
12 changed files with 139 additions and 143 deletions

View File

@ -26,7 +26,7 @@ import org.jboss.logging.annotations.MessageLogger;
/**
* Logger Code 22
*
* each message id must be 6 digits long starting with 10, the 3rd digit donates the level so
* each message id must be 6 digits long starting with 22, the 3rd digit donates the level so
*
* INF0 1
* WARN 2
@ -35,7 +35,7 @@ import org.jboss.logging.annotations.MessageLogger;
* TRACE 5
* FATAL 6
*
* so an INFO message would be 101000 to 101999
* so an INFO message would be 241000 to 246999
*/
@MessageLogger(projectCode = "AMQ")
@ -50,6 +50,10 @@ public interface ActiveMQStompProtocolLogger extends BasicLogger {
@Message(id = 222068, value = "connection closed {0}", format = Message.Format.MESSAGE_FORMAT)
void connectionClosed(StompConnection connection);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 222069, value = "Sent ERROR frame to STOMP client {0}: {1}", format = Message.Format.MESSAGE_FORMAT)
void sentErrorToClient(String address, String message);
@LogMessage(level = Logger.Level.ERROR)
@Message(id = 224023, value = "Unable to send frame {0}", format = Message.Format.MESSAGE_FORMAT)
void errorSendingFrame(@Cause Exception e, StompFrame frame);

View File

@ -16,6 +16,7 @@
*/
package org.apache.activemq.artemis.core.protocol.stomp;
import javax.security.auth.Subject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
@ -31,6 +32,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException;
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
@ -53,8 +55,6 @@ import org.apache.activemq.artemis.utils.ConfigurationHelper;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.VersionLoader;
import javax.security.auth.Subject;
import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProtocolMessageBundle.BUNDLE;
public final class StompConnection implements RemotingConnection {
@ -269,9 +269,8 @@ public final class StompConnection implements RemotingConnection {
}
public void autoCreateDestinationIfPossible(String queue, RoutingType routingType) throws ActiveMQStompException {
ServerSession session = getSession().getCoreSession();
try {
ServerSession session = getSession().getCoreSession();
SimpleString simpleQueue = SimpleString.toSimpleString(queue);
AddressInfo addressInfo = manager.getServer().getAddressInfo(simpleQueue);
AddressSettings addressSettings = manager.getServer().getAddressSettingsRepository().getMatch(queue);
@ -437,10 +436,18 @@ public final class StompConnection implements RemotingConnection {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPasscode() {
return passcode;
}
public void setPasscode(String passcode) {
this.passcode = passcode;
}
@Override
public void setClientID(String clientID) {
this.clientID = clientID;
@ -584,24 +591,15 @@ public final class StompConnection implements RemotingConnection {
manager.sendReply(this, frame, function);
}
public boolean validateUser(final String login, final String pass, final RemotingConnection connection) {
this.valid = manager.validateUser(login, pass, connection);
if (valid) {
this.login = login;
this.passcode = pass;
}
return valid;
}
public CoreMessage createServerMessage() {
return manager.createServerMessage();
}
public StompSession getSession() throws ActiveMQStompException {
public StompSession getSession() throws ActiveMQStompException, ActiveMQSecurityException {
return getSession(null);
}
public StompSession getSession(String txID) throws ActiveMQStompException {
public StompSession getSession(String txID) throws ActiveMQStompException, ActiveMQSecurityException {
StompSession session = null;
try {
if (txID == null) {
@ -609,6 +607,8 @@ public final class StompConnection implements RemotingConnection {
} else {
session = manager.getTransactedSession(this, txID);
}
} catch (ActiveMQSecurityException e) {
throw e;
} catch (Exception e) {
throw BUNDLE.errorGetSession(e).setHandler(frameHandler);
}
@ -623,15 +623,15 @@ public final class StompConnection implements RemotingConnection {
}
protected void sendServerMessage(ICoreMessage message, String txID) throws ActiveMQStompException {
StompSession stompSession = getSession(txID);
if (stompSession.isNoLocal()) {
message.putStringProperty(CONNECTION_ID_PROP, getID().toString());
}
if (isEnableMessageID()) {
message.putStringProperty("amqMessageId", "STOMP" + message.getMessageID());
}
try {
StompSession stompSession = getSession(txID);
if (stompSession.isNoLocal()) {
message.putStringProperty(CONNECTION_ID_PROP, getID().toString());
}
if (isEnableMessageID()) {
message.putStringProperty("amqMessageId", "STOMP" + message.getMessageID());
}
if (minLargeMessageSize == -1 || (message.getBodyBuffer().writerIndex() < minLargeMessageSize)) {
stompSession.sendInternal(message, false);
} else {
@ -778,6 +778,14 @@ public final class StompConnection implements RemotingConnection {
stompListener.replySent(frame);
}
if (frame.getCommand().equals(Stomp.Responses.ERROR)) {
String message = "no message header";
if (frame.hasHeader(Stomp.Headers.Error.MESSAGE)) {
message = frame.getHeader(Stomp.Headers.Error.MESSAGE);
}
ActiveMQStompProtocolLogger.LOGGER.sentErrorToClient(getTransportConnection().getRemoteAddress(), message);
}
}
public VersionedStompFrameHandler getFrameHandler() {

View File

@ -33,7 +33,6 @@ import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.core.io.IOCallback;
import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.core.remoting.CertificateUtil;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
@ -45,9 +44,6 @@ import org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager2;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3;
import org.apache.activemq.artemis.utils.UUIDGenerator;
import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProtocolMessageBundle.BUNDLE;
@ -65,7 +61,7 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
private final Executor executor;
private final Map<String, StompSession> transactedSessions = new HashMap<>();
private final Map<Object, StompSession> transactedSessions = new HashMap<>();
// key => connection ID, value => Stomp session
private final Map<Object, StompSession> sessions = new HashMap<>();
@ -212,33 +208,22 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
}
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
public StompSession getSession(StompConnection connection) throws Exception {
StompSession stompSession = sessions.get(connection.getID());
if (stompSession == null) {
stompSession = new StompSession(connection, this, server.getStorageManager().newContext(server.getExecutorFactory().getExecutor()));
String name = UUIDGenerator.getInstance().generateStringUUID();
ServerSession session = server.createSession(name, connection.getLogin(), connection.getPasscode(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, connection, true, false, false, false, null, stompSession, true, server.newOperationContext(), getPrefixes());
stompSession.setServerSession(session);
sessions.put(connection.getID(), stompSession);
}
server.getStorageManager().setContext(stompSession.getContext());
return stompSession;
return internalGetSession(connection, sessions, connection.getID(), false);
}
public StompSession getTransactedSession(StompConnection connection, String txID) throws Exception {
StompSession stompSession = transactedSessions.get(txID);
return internalGetSession(connection, transactedSessions, txID, true);
}
private StompSession internalGetSession(StompConnection connection, Map<Object, StompSession> sessions, Object id, boolean transacted) throws Exception {
StompSession stompSession = sessions.get(id);
if (stompSession == null) {
stompSession = new StompSession(connection, this, server.getStorageManager().newContext(executor));
stompSession = new StompSession(connection, this, server.getStorageManager().newContext(server.getExecutorFactory().getExecutor()));
String name = UUIDGenerator.getInstance().generateStringUUID();
ServerSession session = server.createSession(name, connection.getLogin(), connection.getPasscode(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, connection, false, false, false, false, null, stompSession, true, server.newOperationContext(), getPrefixes());
ServerSession session = server.createSession(name, connection.getLogin(), connection.getPasscode(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, connection, !transacted, false, false, false, null, stompSession, true, server.newOperationContext(), getPrefixes());
stompSession.setServerSession(session);
transactedSessions.put(txID, stompSession);
sessions.put(id, stompSession);
}
server.getStorageManager().setContext(stompSession.getContext());
return stompSession;
@ -263,9 +248,9 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
}
// removed the transacted session belonging to the connection
Iterator<Entry<String, StompSession>> iterator = transactedSessions.entrySet().iterator();
Iterator<Entry<Object, StompSession>> iterator = transactedSessions.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, StompSession> entry = iterator.next();
Map.Entry<Object, StompSession> entry = iterator.next();
if (entry.getValue().getConnection() == connection) {
ServerSession serverSession = entry.getValue().getCoreSession();
try {
@ -326,24 +311,6 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
return "activemq";
}
public boolean validateUser(String login, String passcode, RemotingConnection remotingConnection) {
boolean validated = true;
ActiveMQSecurityManager sm = server.getSecurityManager();
if (sm != null && server.getConfiguration().isSecurityEnabled()) {
if (sm instanceof ActiveMQSecurityManager3) {
validated = ((ActiveMQSecurityManager3) sm).validateUser(login, passcode, remotingConnection) != null;
} else if (sm instanceof ActiveMQSecurityManager2) {
validated = ((ActiveMQSecurityManager2) sm).validateUser(login, passcode, CertificateUtil.getCertsFromConnection(remotingConnection));
} else {
validated = sm.validateUser(login, passcode);
}
}
return validated;
}
public CoreMessage createServerMessage() {
return new CoreMessage(server.getStorageManager().generateID(), 512);
}

View File

@ -133,6 +133,8 @@ public abstract class VersionedStompFrameHandler {
return null;
} catch (ActiveMQStompException e) {
return e.getFrame();
} catch (Exception e) {
return new ActiveMQStompException(e.getMessage(), e).setHandler(this).getFrame();
}
}
@ -256,7 +258,7 @@ public abstract class VersionedStompFrameHandler {
return response;
}
public StompPostReceiptFunction onSubscribe(StompFrame frame) throws ActiveMQStompException {
public StompPostReceiptFunction onSubscribe(StompFrame frame) throws Exception {
String destination = getDestination(frame);
String selector = frame.getHeader(Stomp.Headers.Subscribe.SELECTOR);
@ -279,11 +281,11 @@ public abstract class VersionedStompFrameHandler {
return connection.subscribe(destination, selector, ack, id, durableSubscriptionName, noLocal, routingType);
}
public String getDestination(StompFrame request) throws ActiveMQStompException {
public String getDestination(StompFrame request) throws Exception {
return getDestination(request, Headers.Subscribe.DESTINATION);
}
public String getDestination(StompFrame request, String header) throws ActiveMQStompException {
public String getDestination(StompFrame request, String header) throws Exception {
String destination = request.getHeader(header);
if (destination == null) {
return null;
@ -291,7 +293,7 @@ public abstract class VersionedStompFrameHandler {
return connection.getSession().getCoreSession().removePrefix(SimpleString.toSimpleString(destination)).toString();
}
public String getPrefix(StompFrame request) throws ActiveMQStompException {
public String getPrefix(StompFrame request) throws Exception {
String destination = request.getHeader(Headers.Send.DESTINATION);
if (destination == null) {
return null;
@ -367,7 +369,7 @@ public abstract class VersionedStompFrameHandler {
connection.destroy();
}
private RoutingType getRoutingType(String typeHeader, String destination) throws ActiveMQStompException {
private RoutingType getRoutingType(String typeHeader, String destination) throws Exception {
// null is valid to return here so we know when the user didn't provide any routing info
RoutingType routingType;
if (typeHeader != null) {
@ -378,4 +380,14 @@ public abstract class VersionedStompFrameHandler {
return routingType;
}
protected StompFrame getFailedAuthenticationResponse(String login) {
StompFrame response;
response = createStompFrame(Stomp.Responses.ERROR);
response.setNeedsDisconnect(true);
String responseText = "Security Error occurred: User name [" + login + "] or password is invalid";
response.setBody(responseText);
response.addHeader(Stomp.Headers.Error.MESSAGE, responseText);
return response;
}
}

View File

@ -21,6 +21,7 @@ import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProto
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
import org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompException;
import org.apache.activemq.artemis.core.protocol.stomp.FrameEventListener;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
@ -54,32 +55,25 @@ public class StompFrameHandlerV10 extends VersionedStompFrameHandler implements
try {
connection.setClientID(clientID);
if (connection.validateUser(login, passcode, connection)) {
connection.setValid(true);
connection.setLogin(login);
connection.setPasscode(passcode);
// Create session which will validate user - this will cache the session in the protocol manager
connection.getSession();
connection.setValid(true);
// Create session after validating user - this will cache the session in the
// protocol manager
connection.getSession();
response = new StompFrameV10(Stomp.Responses.CONNECTED);
response = new StompFrameV10(Stomp.Responses.CONNECTED);
if (frame.hasHeader(Stomp.Headers.ACCEPT_VERSION)) {
response.addHeader(Stomp.Headers.Connected.VERSION, StompVersions.V1_0.toString());
}
response.addHeader(Stomp.Headers.Connected.SESSION, connection.getID().toString());
if (requestID != null) {
response.addHeader(Stomp.Headers.Connected.RESPONSE_ID, requestID);
}
} else {
// not valid
response = new StompFrameV10(Stomp.Responses.ERROR);
String responseText = "Security Error occurred: User name [" + login + "] or password is invalid";
response.setBody(responseText);
response.setNeedsDisconnect(true);
response.addHeader(Stomp.Headers.Error.MESSAGE, responseText);
if (frame.hasHeader(Stomp.Headers.ACCEPT_VERSION)) {
response.addHeader(Stomp.Headers.Connected.VERSION, StompVersions.V1_0.toString());
}
response.addHeader(Stomp.Headers.Connected.SESSION, connection.getID().toString());
if (requestID != null) {
response.addHeader(Stomp.Headers.Connected.RESPONSE_ID, requestID);
}
} catch (ActiveMQSecurityException e) {
response = getFailedAuthenticationResponse(login);
} catch (ActiveMQStompException e) {
response = e.getFrame();
}

View File

@ -24,6 +24,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
import org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompException;
import org.apache.activemq.artemis.core.protocol.stomp.FrameEventListener;
import org.apache.activemq.artemis.core.protocol.stomp.SimpleBytes;
@ -69,50 +70,42 @@ public class StompFrameHandlerV11 extends VersionedStompFrameHandler implements
try {
connection.setClientID(clientID);
if (connection.validateUser(login, passcode, connection)) {
connection.setValid(true);
connection.setLogin(login);
connection.setPasscode(passcode);
// Create session which will validate user - this will cache the session in the protocol manager
connection.getSession();
connection.setValid(true);
// Create session after validating user - this will cache the session in the
// protocol manager
connection.getSession();
response = this.createStompFrame(Stomp.Responses.CONNECTED);
response = this.createStompFrame(Stomp.Responses.CONNECTED);
// version
response.addHeader(Stomp.Headers.Connected.VERSION, connection.getVersion());
// version
response.addHeader(Stomp.Headers.Connected.VERSION, connection.getVersion());
// session
response.addHeader(Stomp.Headers.Connected.SESSION, connection.getID().toString());
// session
response.addHeader(Stomp.Headers.Connected.SESSION, connection.getID().toString());
// server
response.addHeader(Stomp.Headers.Connected.SERVER, connection.getActiveMQServerName());
// server
response.addHeader(Stomp.Headers.Connected.SERVER, connection.getActiveMQServerName());
if (requestID != null) {
response.addHeader(Stomp.Headers.Connected.RESPONSE_ID, requestID);
}
// heart-beat. We need to start after connected frame has been sent.
// otherwise the client may receive heart-beat before it receives
// connected frame.
String heartBeat = headers.get(Stomp.Headers.Connect.HEART_BEAT);
if (heartBeat != null) {
handleHeartBeat(heartBeat);
if (heartBeater == null) {
response.addHeader(Stomp.Headers.Connected.HEART_BEAT, "0,0");
} else {
response.addHeader(Stomp.Headers.Connected.HEART_BEAT, heartBeater.serverPingPeriod + "," + heartBeater.clientPingResponse);
}
}
} else {
// not valid
response = createStompFrame(Stomp.Responses.ERROR);
response.setNeedsDisconnect(true);
response.addHeader(Stomp.Headers.CONTENT_TYPE, "text/plain");
String responseText = "Security Error occurred: User name [" + login + "] or password is invalid";
response.setBody(responseText);
response.addHeader(Stomp.Headers.Error.MESSAGE, responseText);
if (requestID != null) {
response.addHeader(Stomp.Headers.Connected.RESPONSE_ID, requestID);
}
// heart-beat. We need to start after connected frame has been sent.
// otherwise the client may receive heart-beat before it receives
// connected frame.
String heartBeat = headers.get(Stomp.Headers.Connect.HEART_BEAT);
if (heartBeat != null) {
handleHeartBeat(heartBeat);
if (heartBeater == null) {
response.addHeader(Stomp.Headers.Connected.HEART_BEAT, "0,0");
} else {
response.addHeader(Stomp.Headers.Connected.HEART_BEAT, heartBeater.serverPingPeriod + "," + heartBeater.clientPingResponse);
}
}
} catch (ActiveMQSecurityException e) {
response = getFailedAuthenticationResponse(login);
} catch (ActiveMQStompException e) {
response = e.getFrame();
}
@ -120,6 +113,13 @@ public class StompFrameHandlerV11 extends VersionedStompFrameHandler implements
return response;
}
@Override
protected StompFrame getFailedAuthenticationResponse(String login) {
StompFrame response = super.getFailedAuthenticationResponse(login);
response.addHeader(Stomp.Headers.CONTENT_TYPE, "text/plain");
return response;
}
private void handleHeartBeat(String heartBeatHeader) throws ActiveMQStompException {
String[] params = heartBeatHeader.split(",");
if (params.length != 2) {

View File

@ -175,7 +175,6 @@ public class ActiveMQPacketHandler implements ChannelHandler {
response = new CreateSessionResponseMessage(server.getVersion().getIncrementingVersion());
} catch (ActiveMQClusterSecurityException | ActiveMQSecurityException e) {
ActiveMQServerLogger.LOGGER.securityProblemWhileCreatingSession(e.getMessage());
response = new ActiveMQExceptionMessage(e);
} catch (ActiveMQException e) {
if (e.getType() == ActiveMQExceptionType.INCOMPATIBLE_CLIENT_SERVER_VERSIONS) {

View File

@ -29,5 +29,7 @@ public interface SecurityStore {
boolean isSecurityEnabled();
void setSecurityEnabled(boolean securityEnabled);
void stop();
}

View File

@ -30,6 +30,7 @@ import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.security.SecurityAuth;
import org.apache.activemq.artemis.core.security.SecurityStore;
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.core.server.management.NotificationService;
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
@ -59,7 +60,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
private volatile long lastCheck;
private final boolean securityEnabled;
private boolean securityEnabled;
private final String managementClusterUser;
@ -96,6 +97,11 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
return securityEnabled;
}
@Override
public void setSecurityEnabled(boolean securityEnabled) {
this.securityEnabled = securityEnabled;
}
@Override
public void stop() {
securityRepository.unRegisterListener(this);
@ -149,7 +155,11 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
certSubjectDN = certs[0].getSubjectDN().getName();
}
throw ActiveMQMessageBundle.BUNDLE.unableToValidateUser(connection.getRemoteAddress(), user, certSubjectDN);
Exception e = ActiveMQMessageBundle.BUNDLE.unableToValidateUser(connection.getRemoteAddress(), user, certSubjectDN);
ActiveMQServerLogger.LOGGER.securityProblemWhileAuthenticating(e.getMessage());
throw e;
}
return validatedUser;

View File

@ -1361,8 +1361,8 @@ public interface ActiveMQServerLogger extends BasicLogger {
void negativeGlobalAddressSize(long size);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 222216, value = "Security problem while creating session: {0}", format = Message.Format.MESSAGE_FORMAT)
void securityProblemWhileCreatingSession(String message);
@Message(id = 222216, value = "Security problem while authenticating: {0}", format = Message.Format.MESSAGE_FORMAT)
void securityProblemWhileAuthenticating(String message);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 222217, value = "Cannot find connector-ref {0}. The cluster-connection {1} will not be deployed.", format = Message.Format.MESSAGE_FORMAT)

View File

@ -96,7 +96,7 @@ public class StompV11Test extends StompTestBase {
@Test
public void testConnection() throws Exception {
server.getActiveMQServer().getConfiguration().setSecurityEnabled(true);
server.getActiveMQServer().getSecurityStore().setSecurityEnabled(true);
StompClientConnection connection = StompClientConnectionFactory.createClientConnection(v10Uri);
connection.connect(defUser, defPass);

View File

@ -97,7 +97,7 @@ public class StompV12Test extends StompTestBase {
@Test
public void testConnection() throws Exception {
server.getActiveMQServer().getConfiguration().setSecurityEnabled(true);
server.getActiveMQServer().getSecurityStore().setSecurityEnabled(true);
StompClientConnection connection = StompClientConnectionFactory.createClientConnection(v10Uri);
connection.connect(defUser, defPass);