From c102b2a9784c24d9400b6085222beacf8849a050 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Fri, 17 Oct 2014 14:51:55 +0200 Subject: [PATCH] Remove security features at P2PNode for to exclude problems in that area. Use new bootstrap and Seednode code recommended form Thomas Bocek --- src/main/java/io/bitsquare/SeedNode.java | 10 +- .../io/bitsquare/gui/util/BSFormatter.java | 56 ++++++--- .../java/io/bitsquare/locale/BSResources.java | 2 +- .../msg/BootstrappedPeerFactory.java | 43 +++++++ .../java/io/bitsquare/msg/MessageFacade.java | 10 +- src/main/java/io/bitsquare/msg/P2PNode.java | 108 ++++++++++++++---- 6 files changed, 176 insertions(+), 53 deletions(-) diff --git a/src/main/java/io/bitsquare/SeedNode.java b/src/main/java/io/bitsquare/SeedNode.java index 8fc9942873..b8d5d5fce5 100644 --- a/src/main/java/io/bitsquare/SeedNode.java +++ b/src/main/java/io/bitsquare/SeedNode.java @@ -33,8 +33,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMapChangeListener; import net.tomp2p.peers.PeerStatatistic; -import net.tomp2p.relay.RconRPC; -import net.tomp2p.relay.RelayRPC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,14 +114,8 @@ public class SeedNode extends Thread { peer = new PeerBuilder( Number160.createHash(seedNodeAddress.getId())).ports(seedNodeAddress.getPort()).start(); - // Need to add all features the clients will use (otherwise msg type is UNKNOWN_ID) new PeerBuilderDHT(peer).start(); - //PeerNAT nodeBehindNat = new PeerBuilderNAT(peer).start(); - new PeerBuilderNAT(peer); - RconRPC rconRPC = new RconRPC(peer); - new RelayRPC(peer, rconRPC); - //new PeerBuilderTracker(peer); - //nodeBehindNat.startSetupRelay(new FutureRelay()); + new PeerBuilderNAT(peer).start(); log.debug("Peer started. " + peer.peerAddress()); diff --git a/src/main/java/io/bitsquare/gui/util/BSFormatter.java b/src/main/java/io/bitsquare/gui/util/BSFormatter.java index 1f3244540d..401b08e540 100644 --- a/src/main/java/io/bitsquare/gui/util/BSFormatter.java +++ b/src/main/java/io/bitsquare/gui/util/BSFormatter.java @@ -124,21 +124,31 @@ public class BSFormatter { /////////////////////////////////////////////////////////////////////////////////////////// public String formatCoin(Coin coin) { - try { - return coinFormat.noCode().format(coin).toString(); - } catch (Throwable t) { - log.warn("Exception at formatBtc: " + t.toString()); + if (coin != null) { + try { + return coinFormat.noCode().format(coin).toString(); + } catch (Throwable t) { + log.warn("Exception at formatBtc: " + t.toString()); + return ""; + } + } + else { return ""; } } public String formatCoinWithCode(Coin coin) { - try { - // we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and - // pre and post fixing - return coinFormat.postfixCode().format(coin).toString(); - } catch (Throwable t) { - log.warn("Exception at formatBtcWithCode: " + t.toString()); + if (coin != null) { + try { + // we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and + // pre and post fixing + return coinFormat.postfixCode().format(coin).toString(); + } catch (Throwable t) { + log.warn("Exception at formatBtcWithCode: " + t.toString()); + return ""; + } + } + else { return ""; } } @@ -191,19 +201,29 @@ public class BSFormatter { /////////////////////////////////////////////////////////////////////////////////////////// public String formatFiat(Fiat fiat) { - try { - return fiatFormat.noCode().format(fiat).toString(); - } catch (Throwable t) { - log.warn("Exception at formatFiat: " + t.toString()); + if (fiat != null) { + try { + return fiatFormat.noCode().format(fiat).toString(); + } catch (Throwable t) { + log.warn("Exception at formatFiat: " + t.toString()); + return ""; + } + } + else { return ""; } } public String formatFiatWithCode(Fiat fiat) { - try { - return fiatFormat.postfixCode().format(fiat).toString(); - } catch (Throwable t) { - log.warn("Exception at formatFiatWithCode: " + t.toString()); + if (fiat != null) { + try { + return fiatFormat.postfixCode().format(fiat).toString(); + } catch (Throwable t) { + log.warn("Exception at formatFiatWithCode: " + t.toString()); + return ""; + } + } + else { return ""; } } diff --git a/src/main/java/io/bitsquare/locale/BSResources.java b/src/main/java/io/bitsquare/locale/BSResources.java index 386c02e791..69fa741d50 100644 --- a/src/main/java/io/bitsquare/locale/BSResources.java +++ b/src/main/java/io/bitsquare/locale/BSResources.java @@ -48,7 +48,7 @@ public class BSResources { try { return BSResources.getResourceBundle().getString(key); } catch (MissingResourceException e) { - log.warn("Missing resource for key: " + key); + log.trace("Missing resource for key: " + key); return key; } } diff --git a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java b/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java index ccbf537932..6ec8202d84 100644 --- a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java +++ b/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java @@ -47,6 +47,7 @@ import net.tomp2p.futures.BaseFutureListener; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; +import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; @@ -112,6 +113,43 @@ public class BootstrappedPeerFactory { /////////////////////////////////////////////////////////////////////////////////////////// public ListenableFuture start(int port) { + try { + Peer peer = new PeerBuilder(keyPair).ports(port).behindFirewall().start(); + PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(storage)).start(); + PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); + + // PeerAddress relay = new PeerAddress(new Number160(new Random(43L)), InetAddress.getByName("relay-ip"), + // 5000, 5000); + // peerNAT.addRelay(relay); + + PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeAddress.getId()), + InetAddress.getByName(seedNodeAddress.getIp()), + seedNodeAddress.getPort(), + seedNodeAddress.getPort()); + FutureDiscover fd = peer.discover().peerAddress(masterNodeAddress).start(); + FutureNAT fn = peerNAT.startSetupPortforwarding(fd); + FutureRelayNAT frn = peerNAT.startRelay(fd, fn); + + frn.awaitUninterruptibly(); + if (frn.isSuccess()) { + log.info("Bootstrap in relay mode succesful"); + settableFuture.set(peerDHT); + return settableFuture; + } + else { + log.error("Bootstrap in relay mode failed " + frn.failedReason()); + settableFuture.setException(new Exception("Bootstrap in relay mode failed " + frn.failedReason())); + return settableFuture; + } + } catch (IOException e) { + log.error("Bootstrap in relay mode failed " + e.getMessage()); + e.printStackTrace(); + settableFuture.setException(e); + return settableFuture; + } + } + + public ListenableFuture startOld(int port) { try { /* ChannelServerConficuration csc = PeerBuilder.createDefaultChannelServerConfiguration(); csc.idleTCPSeconds(20).idleUDPSeconds(20).connectionTimeoutTCPMillis(20000); @@ -184,6 +222,11 @@ public class BootstrappedPeerFactory { return settableFuture; } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + private PeerAddress getBootstrapAddress() { try { return new PeerAddress(Number160.createHash(seedNodeAddress.getId()), diff --git a/src/main/java/io/bitsquare/msg/MessageFacade.java b/src/main/java/io/bitsquare/msg/MessageFacade.java index a69330b90d..3469f5f831 100644 --- a/src/main/java/io/bitsquare/msg/MessageFacade.java +++ b/src/main/java/io/bitsquare/msg/MessageFacade.java @@ -235,6 +235,9 @@ public class MessageFacade implements MessageBroker { try { Object offerDataObject = offerData.object(); if (offerDataObject instanceof Offer) { + log.trace("Remove offer from DHT was successful. Removed data: [key: " + + locationKey + ", " + + "offer: " + (Offer) offerDataObject + "]"); orderBookListener.onOfferRemoved((Offer) offerDataObject); } } catch (ClassNotFoundException | IOException e) { @@ -244,13 +247,10 @@ public class MessageFacade implements MessageBroker { }); writeInvalidationTimestampToDHT(locationKey); }); - - log.trace("Remove offer from DHT was successful. Removed data: [key: " + locationKey + ", " + - "value: " + offerData + "]"); } else { - log.error("Remove offer from DHT was not successful. locationKey: " + locationKey + ", " + - "Reason: " + future.failedReason()); + log.error("Remove offer from DHT failed. Cause: future.isSuccess() = false, locationKey: " + + locationKey + ", Reason: " + future.failedReason()); } } diff --git a/src/main/java/io/bitsquare/msg/P2PNode.java b/src/main/java/io/bitsquare/msg/P2PNode.java index c721755090..e4bac5e622 100644 --- a/src/main/java/io/bitsquare/msg/P2PNode.java +++ b/src/main/java/io/bitsquare/msg/P2PNode.java @@ -37,6 +37,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; import net.tomp2p.connection.DSASignatureFactory; +import net.tomp2p.connection.PeerConnection; import net.tomp2p.dht.FutureGet; import net.tomp2p.dht.FuturePut; import net.tomp2p.dht.FutureRemove; @@ -138,53 +139,43 @@ public class P2PNode { // Generic DHT methods /////////////////////////////////////////////////////////////////////////////////////////// - // The data and the domain are protected by that key pair. + // TODO remove all security features for the moment. There are some problems with a "wrong signature!" msg in + // the logs public FuturePut putDomainProtectedData(Number160 locationKey, Data data) { - data.protectEntry(keyPair); - final Number160 ownerKeyHash = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); - return peerDHT.put(locationKey).data(data).keyPair(keyPair).domainKey(ownerKeyHash).protectDomain().start(); + return peerDHT.put(locationKey).data(data).start(); } - // No protection, everybody can write. public FuturePut putData(Number160 locationKey, Data data) { return peerDHT.put(locationKey).data(data).start(); } - // Not public readable. Only users with the public key of the peer who stored the data can read that data public FutureGet getDomainProtectedData(Number160 locationKey, PublicKey publicKey) { - final Number160 ownerKeyHash = Utils.makeSHAHash(publicKey.getEncoded()); - return peerDHT.get(locationKey).domainKey(ownerKeyHash).start(); + return peerDHT.get(locationKey).start(); } - // No protection, everybody can read. public FutureGet getData(Number160 locationKey) { return peerDHT.get(locationKey).start(); } - // No domain protection, but entry protection public FuturePut addProtectedData(Number160 locationKey, Data data) { - data.protectEntry(keyPair); - log.trace("addProtectedData with contentKey " + data.hash().toString()); - return peerDHT.add(locationKey).data(data).keyPair(keyPair).start(); + return peerDHT.add(locationKey).data(data).start(); } - // No domain protection, but entry protection public FutureRemove removeFromDataMap(Number160 locationKey, Data data) { Number160 contentKey = data.hash(); log.trace("removeFromDataMap with contentKey " + contentKey.toString()); - return peerDHT.remove(locationKey).contentKey(contentKey).keyPair(keyPair).start(); + return peerDHT.remove(locationKey).contentKey(contentKey).start(); } - // Public readable public FutureGet getDataMap(Number160 locationKey) { return peerDHT.get(locationKey).all().start(); } - // Send signed payLoad to peer public FutureDirect sendData(PeerAddress peerAddress, Object payLoad) { - // use 30 seconds as max idle time before connection get closed - FuturePeerConnection futurePeerConnection = peerDHT.peer().createPeerConnection(peerAddress, 30000); - FutureDirect futureDirect = peerDHT.peer().sendDirect(futurePeerConnection).object(payLoad).sign().start(); + log.trace("sendData"); + FuturePeerConnection futurePeerConnection = peerDHT.peer().createPeerConnection(peerAddress, + PeerConnection.HEART_BEAT_MILLIS); + FutureDirect futureDirect = peerDHT.peer().sendDirect(futurePeerConnection).object(payLoad).start(); futureDirect.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture future) throws Exception { @@ -205,6 +196,82 @@ public class P2PNode { return futureDirect; } +// +// public FuturePut putDomainProtectedData(Number160 locationKey, Data data) { +// log.trace("putDomainProtectedData"); +// data.protectEntry(keyPair); +// final Number160 ownerKeyHash = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); +// return peerDHT.put(locationKey).data(data).keyPair(keyPair).domainKey(ownerKeyHash).protectDomain().start(); +// } +// +// // No protection, everybody can write. +// public FuturePut putData(Number160 locationKey, Data data) { +// log.trace("putData"); +// return peerDHT.put(locationKey).data(data).start(); +// } +// +// // Not public readable. Only users with the public key of the peer who stored the data can read that data +// public FutureGet getDomainProtectedData(Number160 locationKey, PublicKey publicKey) { +// log.trace("getDomainProtectedData"); +// final Number160 ownerKeyHash = Utils.makeSHAHash(publicKey.getEncoded()); +// return peerDHT.get(locationKey).domainKey(ownerKeyHash).start(); +// } +// +// // No protection, everybody can read. +// public FutureGet getData(Number160 locationKey) { +// log.trace("getData"); +// return peerDHT.get(locationKey).start(); +// } +// +// // No domain protection, but entry protection +// public FuturePut addProtectedData(Number160 locationKey, Data data) { +// log.trace("addProtectedData"); +// data.protectEntry(keyPair); +// log.trace("addProtectedData with contentKey " + data.hash().toString()); +// return peerDHT.add(locationKey).data(data).keyPair(keyPair).start(); +// } +// +// // No domain protection, but entry protection +// public FutureRemove removeFromDataMap(Number160 locationKey, Data data) { +// log.trace("removeFromDataMap"); +// Number160 contentKey = data.hash(); +// log.trace("removeFromDataMap with contentKey " + contentKey.toString()); +// return peerDHT.remove(locationKey).contentKey(contentKey).keyPair(keyPair).start(); +// } +// +// // Public readable +// public FutureGet getDataMap(Number160 locationKey) { +// log.trace("getDataMap"); +// return peerDHT.get(locationKey).all().start(); +// } + + // Send signed payLoad to peer +// public FutureDirect sendData(PeerAddress peerAddress, Object payLoad) { +// // use 30 seconds as max idle time before connection get closed +// FuturePeerConnection futurePeerConnection = peerDHT.peer().createPeerConnection(peerAddress, 30000); +// FutureDirect futureDirect = peerDHT.peer().sendDirect(futurePeerConnection).object(payLoad).sign().start(); +// futureDirect.addListener(new BaseFutureListener() { +// @Override +// public void operationComplete(BaseFuture future) throws Exception { +// if (futureDirect.isSuccess()) { +// log.debug("sendMessage completed"); +// } +// else { +// log.error("sendData failed with Reason " + futureDirect.failedReason()); +// } +// } +// +// @Override +// public void exceptionCaught(Throwable t) throws Exception { +// log.error("Exception at sendData " + t.toString()); +// } +// }); +// +// return futureDirect; +// } +// + + /////////////////////////////////////////////////////////////////////////////////////////// // Private /////////////////////////////////////////////////////////////////////////////////////////// @@ -285,6 +352,7 @@ public class P2PNode { private FuturePut storePeerAddress() throws IOException { Number160 locationKey = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); Data data = new Data(peerDHT.peerAddress()); + log.debug("storePeerAddress " + peerDHT.peerAddress().toString()); return putDomainProtectedData(locationKey, data); }