use of won.protocol.message.WonMessage in project webofneeds by researchstudio-sat.
the class SignatureCheckingWonMessageProcessor method process.
@Override
public WonMessage process(final WonMessage message) throws WonMessageProcessingException {
StopWatch sw = new StopWatch();
try {
SignatureVerificationState result;
/*
* If the message is a successResponse to a delete Message then we can't check
* the signature as it is stored in the deleted Atom, so we just accept the
* message as valid and return it.
*/
if (message.getRespondingToMessageType() == WonMessageType.DELETE && message.getMessageType() == WonMessageType.SUCCESS_RESPONSE) {
return message;
}
for (WonMessage toCheck : message.getAllMessages()) {
try {
// obtain public keys
sw.start("get public keys");
Map<String, PublicKey> keys = WonKeysReaderWriter.readKeyFromMessage(toCheck);
WonMessageType type = toCheck.getMessageType();
switch(type) {
case CREATE_ATOM:
if (keys.isEmpty()) {
throw new WonMessageProcessingException("No key found in CREATE message");
}
break;
case REPLACE:
if (keys.isEmpty()) {
keys.putAll(getRequiredPublicKeys(toCheck.getCompleteDataset()));
}
break;
default:
if (!keys.isEmpty()) {
throw new WonMessageProcessingException(String.format("An Atom key may only be embedded in CREATE or REPLACE messages! Found one in %s message %s", type, message.getMessageURIRequired()));
}
keys.putAll(getRequiredPublicKeys(toCheck.getCompleteDataset()));
}
sw.stop();
// verify with those public keys
sw.start("verify");
result = WonMessageSignerVerifier.verify(keys, toCheck);
sw.stop();
if (logger.isDebugEnabled()) {
logger.debug("VERIFIED=" + result.isVerificationPassed() + " with keys: " + keys.values() + " for\n" + RdfUtils.writeDatasetToString(Prefixer.setPrefixes(toCheck.getCompleteDataset()), Lang.TRIG));
}
} catch (LinkedDataFetchingException e) {
/*
* If a delete message could not be validated because the atom was already
* deleted, we assume that this message is just mirrored back to the owner and
* is to be accepteed
*/
if (WonMessageType.DELETE.equals(toCheck.getMessageType())) {
if (e.getCause() instanceof HttpClientErrorException && HttpStatus.GONE.equals(((HttpClientErrorException) e.getCause()).getStatusCode())) {
if (logger.isDebugEnabled()) {
logger.debug("Failure during processing signature check of message" + toCheck.getMessageURI() + " (messageType was DELETE, but atom is already deleted, accept message anyway)");
}
return toCheck;
}
}
// TODO SignatureProcessingException?
throw new WonMessageProcessingException("Could not verify message " + toCheck.getMessageURI(), e);
} catch (Exception e) {
// TODO SignatureProcessingException?
throw new WonMessageProcessingException("Could not verify message " + toCheck.getMessageURI(), e);
}
// throw exception if the verification fails:
if (!result.isVerificationPassed()) {
String errormessage = "Message verification failed. Message:" + toCheck.toStringForDebug(false) + ", Problem:" + result.getMessage();
if (logger.isDebugEnabled()) {
logger.debug(errormessage + ". Offending message:\n" + RdfUtils.toString(Prefixer.setPrefixes(toCheck.getCompleteDataset())));
}
// TODO SignatureProcessingException?
throw new WonMessageProcessingException(new SignatureException(errormessage + ". To log the offending message, set Loglevel to DEBUG for logger '" + this.getClass().getName() + "'"));
}
}
return message;
} finally {
logger.debug(LogMarkers.TIMING, "Signature check for message {} took {} millis, details:\n {}", new Object[] { message.getMessageURIRequired(), sw.getTotalTimeMillis(), sw.prettyPrint() });
}
}
use of won.protocol.message.WonMessage in project webofneeds by researchstudio-sat.
the class VerifyAndSignExamples method nodeCreateAtomMsg.
@Test
public /*
* Node receives create atom message, verifies it, if verification succeeds -
* adds envelope that includes reference to verified signatures, and signs it.
*/
void nodeCreateAtomMsg() throws Exception {
// create dataset that contains atom core data graph, envelope and its
// signatures.
// this is what nodes receives when the atom is created
Dataset inputDataset = TestSigningUtils.prepareTestDatasetFromNamedGraphs(RESOURCE_FILE, new String[] { ATOM_CORE_DATA_URI, ATOM_CORE_DATA_SIG_URI, EVENT_ENV1_URI, EVENT_ENV1_SIG_URI });
WonMessage inputMessage = WonMessage.of(inputDataset);
// node verifies the signature:
WonMessage verifiedMessage = null;
try {
verifiedMessage = checkingProcessor.process(inputMessage);
} catch (WonMessageProcessingException e) {
Assert.fail("Signature verification failed");
}
// write for debugging
// TestSigningUtils.writeToTempFile(outputDataset);
// everyone should be able to verify this message, inculding when it was read
// from RDF:
String datasetString = RdfUtils.writeDatasetToString(inputMessage.getCompleteDataset(), Lang.TRIG);
WonMessage outputMessage = WonMessage.of(RdfUtils.readDatasetFromString(datasetString, Lang.TRIG));
try {
checkingProcessor.process(outputMessage);
} catch (WonMessageProcessingException e) {
Assert.fail("Signature verification failed");
}
}
use of won.protocol.message.WonMessage in project webofneeds by researchstudio-sat.
the class WonVerifierTest method testVerifyCreateAtomData.
@Test
public void testVerifyCreateAtomData() throws Exception {
// create dataset that contains atom core data graph and its signature graph
Dataset testDataset = TestSigningUtils.prepareTestDatasetFromNamedGraphs(RESOURCE_FILE, new String[] { ATOM_CORE_DATA_URI, ATOM_CORE_DATA_SIG_URI });
WonMessage msg = WonMessage.of(testDataset);
// verify
WonVerifier verifier = new WonVerifier(msg);
// TODO load public keys from certificate referenced from signatures
boolean verified = verifier.verify(keys.getPublicKeys());
SignatureVerificationState result = verifier.getVerificationResult();
Assert.assertTrue(result.getMessage(), verified);
Assert.assertEquals(1, result.getSignatureGraphNames().size());
Assert.assertEquals(ATOM_CORE_DATA_URI, result.getSignedGraphNames(ATOM_CORE_DATA_SIG_URI));
// modify a model and check that it does not verify..
Model m = testDataset.getNamedModel(ATOM_CORE_DATA_URI);
Statement stmt = m.listStatements().nextStatement();
m.remove(stmt);
verifier = new WonVerifier(WonMessage.of(testDataset));
verified = verifier.verify(keys.getPublicKeys());
result = verifier.getVerificationResult();
Assert.assertFalse(verified);
Assert.assertEquals(1, result.getSignatureGraphNames().size());
Assert.assertEquals(ATOM_CORE_DATA_URI, result.getSignedGraphNames(ATOM_CORE_DATA_SIG_URI));
// add the removed statement back
m.add(stmt);
verifier = new WonVerifier(WonMessage.of(testDataset));
verified = verifier.verify(keys.getPublicKeys());
// now it should verify again
Assert.assertTrue(verified);
}
use of won.protocol.message.WonMessage in project webofneeds by researchstudio-sat.
the class WonMessageRoutesExternalRoutedTest method test_connect__try_force_racecondition.
@Test
// @Rollback would't work as camel still commits
@Commit
public void test_connect__try_force_racecondition() throws Exception {
for (int i = 0; i < 10; i++) {
logger.debug("Attempt #{} to force a race condition", i + 1);
URI atomURI = newAtomURI();
URI socketURI = URI.create(atomURI.toString() + "#socket1");
URI atomURI2 = newAtomURI();
URI socketURI2 = URI.create(atomURI2.toString() + "#socket1");
prepareMockitoStubs(atomURI, socketURI, atomURI2, socketURI2);
WonMessage createAtom1Msg = prepareFromOwner(makeCreateAtomMessage(atomURI, "/won/node/WonMessageRoutesTest/data/test-atom1.ttl"));
WonMessage createAtom2Msg = prepareFromOwner(makeCreateAtomMessage(atomURI2, "/won/node/WonMessageRoutesTest/data/test-atom1.ttl"));
// set minimal expectations just so we can expect something and subsequently
// reset expectations
toMatcherMockEndpoint.reset();
toOwnerMockEndpoint.reset();
toOwnerMockEndpoint.expectedMessageCount(2);
toMatcherMockEndpoint.expectedMessageCount(2);
sendFromOwner(createAtom1Msg, OWNERAPPLICATION_ID_OWNER1);
sendFromOwner(createAtom2Msg, OWNERAPPLICATION_ID_OWNER2);
WonMessage socketHintMessage = prepareFromMatcher(WonMessageBuilder.socketHint().recipientSocket(socketURI).hintTargetSocket(socketURI2).hintScore(0.5).build());
assertMockEndpointsSatisfiedAndReset(toOwnerMockEndpoint, toMatcherMockEndpoint);
// seems fair to wait for response to create before we send the hint
toOwnerMockEndpoint.expectedMessageCount(1);
sendFromMatcher(socketHintMessage);
assertMockEndpointsSatisfiedAndReset(toOwnerMockEndpoint, toMatcherMockEndpoint);
// start connecting
WonMessage connectFromExternalMsg = prepareFromExternalOwner(WonMessageBuilder.connect().sockets().sender(socketURI2).recipient(socketURI).content().text("Unittest connect").build());
assertMockEndpointsSatisfiedAndReset(toOwnerMockEndpoint, toMatcherMockEndpoint);
WonMessage connectFromOwnerMsg = prepareFromOwner(WonMessageBuilder.connect().sockets().sender(socketURI).recipient(socketURI2).content().text("Unittest connect").build());
toOwnerMockEndpoint.expectedMessageCount(6);
toOwnerMockEndpoint.expectedMessagesMatches(or(maxOnce(isMessageAndResponse(connectFromExternalMsg)), maxOnce(isMessageAndResponseAndRemoteResponse(connectFromExternalMsg)), maxOnce(isSuccessResponseTo(connectFromExternalMsg)), maxOnce(isMessageAndResponse(connectFromOwnerMsg)), maxOnce(isMessageAndResponseAndRemoteResponse(connectFromOwnerMsg)), maxOnce(isSuccessResponseTo(connectFromOwnerMsg))));
Thread t1 = new Thread(() -> helper.doInSeparateTransaction(() -> sendFromOwner(connectFromExternalMsg, OWNERAPPLICATION_ID_OWNER2)));
Thread t2 = new Thread(() -> helper.doInSeparateTransaction(() -> sendFromOwner(connectFromOwnerMsg, OWNERAPPLICATION_ID_OWNER1)));
t1.start();
t2.start();
t1.join();
t2.join();
assertMockEndpointsSatisfiedAndReset(toOwnerMockEndpoint, toMatcherMockEndpoint);
Optional<Connection> con = connectionRepository.findOneBySocketURIAndTargetSocketURI(socketURI, socketURI2);
Connection expected = new Connection();
expected.setState(ConnectionState.CONNECTED);
expected.setAtomURI(atomURI);
expected.setSocketURI(socketURI);
expected.setTargetSocketURI(socketURI2);
expected.setTargetAtomURI(atomURI2);
assertConnectionAsExpected(expected, con);
con = connectionRepository.findOneBySocketURIAndTargetSocketURI(socketURI2, socketURI);
expected = new Connection();
expected.setState(ConnectionState.CONNECTED);
expected.setAtomURI(atomURI2);
expected.setSocketURI(socketURI2);
expected.setTargetSocketURI(socketURI);
expected.setTargetAtomURI(atomURI);
assertConnectionAsExpected(expected, con);
}
}
use of won.protocol.message.WonMessage in project webofneeds by researchstudio-sat.
the class WonMessageRoutesExternalRoutedTest method test_conversation__proposal_rejected.
@Test
// @Rollback would't work as camel still commits
@Commit
public void test_conversation__proposal_rejected() throws Exception {
URI atomURI = newAtomURI();
URI socketURI = URI.create(atomURI.toString() + "#socket1");
URI atomURI2 = newAtomURI();
URI socketURI2 = URI.create(atomURI2.toString() + "#socket1");
prepareMockitoStubs(atomURI, socketURI, atomURI2, socketURI2);
MessageCollector collector = new MessageCollector();
WonMessage createAtom1Msg = prepareFromOwner(makeCreateAtomMessage(atomURI, "/won/node/WonMessageRoutesTest/data/test-atom1.ttl"));
WonMessage createAtom2Msg = prepareFromOwner(makeCreateAtomMessage(atomURI2, "/won/node/WonMessageRoutesTest/data/test-atom1.ttl"));
// set minimal expectations just so we can expect something and subsequently
// reset expectations
toOwnerMockEndpoint.expectedMessageCount(2);
toMatcherMockEndpoint.expectedMessageCount(2);
sendFromOwner(createAtom1Msg, OWNERAPPLICATION_ID_OWNER1);
sendFromOwner(createAtom2Msg, OWNERAPPLICATION_ID_OWNER2);
WonMessage socketHintMessage = prepareFromMatcher(WonMessageBuilder.socketHint().recipientSocket(socketURI).hintTargetSocket(socketURI2).hintScore(0.5).build());
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
toOwnerMockEndpoint.expectedMessageCount(1);
toMatcherMockEndpoint.expectedMessageCount(0);
sendFromMatcher(socketHintMessage);
// start connecting
WonMessage connectFromExternalMsg = prepareFromExternalOwner(WonMessageBuilder.connect().sockets().sender(socketURI2).recipient(socketURI).content().text("Unittest connect").build());
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
toMatcherMockEndpoint.expectedMessageCount(0);
toOwnerMockEndpoint.expectedMessageCount(3);
sendFromOwner(connectFromExternalMsg, OWNERAPPLICATION_ID_OWNER2);
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
WonMessage connectFromOwnerMsg = prepareFromOwner(WonMessageBuilder.connect().sockets().sender(socketURI).recipient(socketURI2).content().text("Unittest connect (completing the handshake)").build());
toOwnerMockEndpoint.expectedMessageCount(3);
toMatcherMockEndpoint.expectedMessageCount(2);
sendFromOwner(connectFromOwnerMsg, OWNERAPPLICATION_ID_OWNER1);
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
// // connect done
Optional<Connection> con = connectionRepository.findOneBySocketURIAndTargetSocketURI(socketURI, socketURI2);
// // send one message, which will be the content of the agreement
WonMessage contentForProposal = prepareFromOwner(WonMessageBuilder.connectionMessage().sockets().sender(con.get().getSocketURI()).recipient(con.get().getTargetSocketURI()).content().text(// something important
"We are best friends forever!").build());
toOwnerMockEndpoint.expectedMessageCount(3);
toMatcherMockEndpoint.expectedMessageCount(0);
sendFromOwner(contentForProposal, OWNERAPPLICATION_ID_OWNER1);
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
// now propose the previous message formally
WonMessage proposal = prepareFromOwner(WonMessageBuilder.connectionMessage().sockets().sender(con.get().getSocketURI()).recipient(con.get().getTargetSocketURI()).content().text("I am hereby proposing to be best friends forever").agreement().proposes(contentForProposal).build());
toOwnerMockEndpoint.expectedMessageCount(3);
toMatcherMockEndpoint.expectedMessageCount(0);
sendFromOwner(proposal, OWNERAPPLICATION_ID_OWNER1);
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
// now accept the proposal from the other side
WonMessage rejectMessage = prepareFromExternalOwner(WonMessageBuilder.connectionMessage().sockets().sender(con.get().getTargetSocketURI()).recipient(con.get().getSocketURI()).content().text("I am sorry, do I know you?").agreement().rejects(proposal.getMessageURI()).build());
toOwnerMockEndpoint.expectedMessageCount(3);
toMatcherMockEndpoint.expectedMessageCount(0);
sendFromOwner(rejectMessage, OWNERAPPLICATION_ID_OWNER2);
assertMockEndpointsSatisfiedAndReset(collector, toOwnerMockEndpoint, toMatcherMockEndpoint);
printConversationIfDebugging(collector);
assertCorrectAgreements("Wrong agreement content", collector.getCollected(), DatasetFactory.createGeneral());
}
Aggregations