added optional SSL encryption

This commit is contained in:
betasteward 2015-05-28 21:04:53 -04:00
parent a168d53966
commit b41cbe2703
11 changed files with 55 additions and 13 deletions

View file

@ -699,7 +699,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
public boolean connect(Connection connection) {
client = new Client(instance);
boolean result = client.connect(connection.getUsername(), connection.getHost(), connection.getPort(), version);
boolean result = client.connect(connection.getUsername(), connection.getHost(), connection.getPort(), true, version);
return result;
}

View file

@ -61,7 +61,7 @@ public class MultiConnectTest {
connection.setPort(17171);
connection.setProxyType(Connection.ProxyType.NONE);
client.connect(username, "localhost", 17171, version);
client.connect(username, "localhost", 17171, true, version);
}
public MageVersion getVersion() {
@ -75,6 +75,7 @@ public class MultiConnectTest {
connected++;
}
@Override
public void disconnected(boolean errorCall) {
logger.info("disconnected");
}
@ -158,8 +159,8 @@ public class MultiConnectTest {
private void sleep(int ms) {
try {
Thread.sleep(ms);
} catch (Exception e) {
e.printStackTrace();
} catch (InterruptedException e) {
logger.error("Error", e);
}
}
}

View file

@ -10,11 +10,14 @@ import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.net.ssl.SSLException;
import mage.cards.decks.DeckCardLists;
import mage.constants.ManaType;
import mage.constants.PlayerAction;
@ -59,9 +62,12 @@ public class Client {
private final ClientRegisteredMessageHandler clientRegisteredMessageHandler;
private final ServerMessageHandler serverMessageHandler;
private SslContext sslCtx;
private Channel channel;
private EventLoopGroup group;
private String username;
private String username;
private String host;
private int port;
public Client(MageClient client) {
this.client = client;
@ -73,12 +79,19 @@ public class Client {
serverMessageHandler = new ServerMessageHandler();
}
public boolean connect(String userName, String host, int port, MageVersion version) {
public boolean connect(String userName, String host, int port, boolean ssl, MageVersion version) {
this.username = userName;
this.host = host;
this.port = port;
group = new NioEventLoopGroup();
try {
if (ssl) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
@ -90,7 +103,7 @@ public class Client {
clientRegisteredMessageHandler.registerClient();
client.connected(userName + "@" + host + ":" + port + " ");
return true;
} catch (InterruptedException ex) {
} catch (SSLException | InterruptedException ex) {
logger.fatal("Error connecting", ex);
client.inform("Error connecting", MessageType.ERROR);
group.shutdownGracefully();
@ -103,6 +116,9 @@ public class Client {
@Override
public void initChannel(SocketChannel ch) throws Exception {
if (sslCtx != null) {
ch.pipeline().addLast(sslCtx.newHandler(ch.alloc(), host, port));
}
ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
ch.pipeline().addLast(new ObjectEncoder());

View file

@ -14,6 +14,8 @@ import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
@ -47,6 +49,8 @@ public class Server {
private static final int IDLE_TIMEOUT = 60;
public static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
private SslContext sslCtx;
private final HeartbeatHandler heartbeatHandler;
private final PingMessageHandler pingMessageHandler = new PingMessageHandler();
@ -69,7 +73,15 @@ public class Server {
serverMessageHandler = new ServerMessageHandler(server);
}
public void start(int port) {
public void start(int port, boolean ssl) throws Exception {
if (ssl) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
@ -95,6 +107,9 @@ public class Server {
@Override
public void initChannel(SocketChannel ch) throws Exception {
if (sslCtx != null) {
ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()));
}
ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
ch.pipeline().addLast(new ObjectEncoder());

View file

@ -35,6 +35,7 @@
userNamePattern="[^a-z0-9_]"
maxAiOpponents="15"
saveGameActivated="false"
useSSL="true"
/>
<playerTypes>
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>

View file

@ -212,7 +212,7 @@ public class Main implements MageServer {
try {
instance = new Main(adminPassword, testMode);
server = new Server(instance);
server.start(config.getPort());
server.start(config.getPort(), config.isUseSSL());
// Parameter: serializationtype => jboss
// InvokerLocator serverLocator = new InvokerLocator(connection.getURI());
// if (!isAlreadyRunning(serverLocator)) {
@ -1320,7 +1320,7 @@ public class Main implements MageServer {
return (MatchType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) {
logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder", ex);
} catch (Exception ex) {
} catch (MalformedURLException | InstantiationException | IllegalAccessException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
}
return null;
@ -1333,7 +1333,7 @@ public class Main implements MageServer {
return (TournamentType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) {
logger.warn("Tournament type not found:" + plugin.getName() + " / "+ plugin.getJar() + " - check plugin folder", ex);
} catch (Exception ex) {
} catch (MalformedURLException | InstantiationException | IllegalAccessException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
}
return null;

View file

@ -61,6 +61,7 @@ public class Config {
maxUserNameLength = Integer.parseInt(p.getProperty("maxUserNameLength"));
userNamePattern = p.getProperty("userNamePattern");
saveGameActivated = Boolean.parseBoolean(p.getProperty("saveGameActivated"));
useSSL = Boolean.parseBoolean(p.getProperty("useSSL"));
}
public static final String remoteServer;
@ -76,5 +77,6 @@ public class Config {
public static final int maxUserNameLength;
public static final String userNamePattern;
public static final boolean saveGameActivated;
public static final boolean useSSL;
}

View file

@ -31,6 +31,7 @@
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="useSSL" type="xs:boolean" use="optional"/>
</xs:complexType>
</xs:element>

View file

@ -120,8 +120,12 @@ public class ConfigSettings {
}
public Boolean isSaveGameActivated() {
return config.getServer().isSaveGameActivated();
}
return config.getServer().isSaveGameActivated();
}
public Boolean isUseSSL() {
return config.getServer().isUseSSL();
}
public List<Plugin> getPlayerTypes() {
return config.getPlayerTypes().getPlayerType();

View file

@ -16,6 +16,7 @@
userNamePattern="[^a-z0-9_]"
maxAiOpponents="15"
saveGameActivated="false"
useSSL="true"
/>
<playerTypes>
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>

View file

@ -32,6 +32,7 @@
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="useSSL" type="xs:boolean" use="optional"/>
</xs:complexType>
</xs:element>