Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4D85A183D4 for ; Tue, 1 Mar 2016 14:14:25 +0000 (UTC) Received: (qmail 8345 invoked by uid 500); 1 Mar 2016 14:14:12 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 8281 invoked by uid 500); 1 Mar 2016 14:14:12 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 8272 invoked by uid 99); 1 Mar 2016 14:14:12 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 01 Mar 2016 14:14:12 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 43495DFCB8; Tue, 1 Mar 2016 14:14:12 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <7db0e1804f7b4b949fa50ccdc7815826@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: Updating JwsJson consumers to make the non-validated parts available if needed Date: Tue, 1 Mar 2016 14:14:12 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.1.x-fixes cfedf8a9f -> 6ee6ff05c Updating JwsJson consumers to make the non-validated parts available if needed Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/6ee6ff05 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/6ee6ff05 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/6ee6ff05 Branch: refs/heads/3.1.x-fixes Commit: 6ee6ff05cc62a5ee2126df54952b1afb8045458b Parents: cfedf8a Author: Sergey Beryozkin Authored: Tue Mar 1 14:12:30 2016 +0000 Committer: Sergey Beryozkin Committed: Tue Mar 1 14:13:59 2016 +0000 ---------------------------------------------------------------------- .../jaxrs/JwsJsonContainerRequestFilter.java | 15 ++++++- .../rs/security/jose/jws/JwsJsonConsumer.java | 47 ++++++++++++++------ .../security/jose/jws/JwsJsonConsumerTest.java | 39 ++++++++++++++++ 3 files changed, 86 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/6ee6ff05/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java index d35ec19..1f42701 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java @@ -31,6 +31,7 @@ import javax.ws.rs.container.PreMatching; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.rs.security.jose.common.JoseUtils; +import org.apache.cxf.rs.security.jose.jws.JwsException; import org.apache.cxf.rs.security.jose.jws.JwsJsonConsumer; import org.apache.cxf.rs.security.jose.jws.JwsJsonSignatureEntry; import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; @@ -44,13 +45,23 @@ public class JwsJsonContainerRequestFilter extends AbstractJwsJsonReaderProvider return; } List theSigVerifiers = getInitializedSigVerifiers(); + if (theSigVerifiers.isEmpty()) { + context.abortWith(JAXRSUtils.toResponse(400)); + return; + } JwsJsonConsumer p = new JwsJsonConsumer(IOUtils.readStringFromStream(context.getEntityStream())); - if (isStrictVerification() && p.getSignatureEntries().size() != theSigVerifiers.size() - || !p.verifySignatureWith(theSigVerifiers)) { + try { + List remaining = p.verifyAndGetNonValidated(theSigVerifiers, + isStrictVerification()); + if (!remaining.isEmpty()) { + JAXRSUtils.getCurrentMessage().put("jws.json.remaining.entries", remaining); + } + } catch (JwsException ex) { context.abortWith(JAXRSUtils.toResponse(400)); return; } + byte[] bytes = p.getDecodedJwsPayloadBytes(); context.setEntityStream(new ByteArrayInputStream(bytes)); context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); http://git-wip-us.apache.org/repos/asf/cxf/blob/6ee6ff05/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java index 3ad5b45..e8d9a41 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java @@ -140,19 +140,29 @@ public class JwsJsonConsumer { public boolean verifySignatureWith(byte[] key, SignatureAlgorithm algo) { return verifySignatureWith(JwsUtils.getHmacSignatureVerifier(key, algo)); } + public boolean verifySignatureWith(List validators) { + return verifySignatureWith(validators, false); + } + + public boolean verifySignatureWith(List validators, + boolean validateAll) { try { - if (verifyAndGetNonValidated(validators).isEmpty()) { - return true; - } + verifyAndGetNonValidated(validators, validateAll); } catch (JwsException ex) { - // ignore + LOG.warning("One of JSON JWS signatures is invalid"); + return false; } - LOG.warning("One of JSON JWS signatures is invalid"); - return false; + return true; } + public List verifyAndGetNonValidated(List validators) { - // TODO: more effective approach is needed + return verifyAndGetNonValidated(validators, false); + } + + + public List verifyAndGetNonValidated(List validators, + boolean validateAll) { List validatedSignatures = new LinkedList(); for (JwsSignatureVerifier validator : validators) { List theSignatureEntries = @@ -166,24 +176,35 @@ public class JwsJsonConsumer { } } } + if (validatedSignatures.isEmpty()) { + throw new JwsException(JwsException.Error.INVALID_SIGNATURE); + } List nonValidatedSignatures = new LinkedList(); for (JwsJsonSignatureEntry sigEntry : signatures) { if (!validatedSignatures.contains(sigEntry)) { nonValidatedSignatures.add(sigEntry); } } + if (validateAll && !nonValidatedSignatures.isEmpty()) { + throw new JwsException(JwsException.Error.INVALID_SIGNATURE); + } return nonValidatedSignatures; } - + public String verifyAndProduce(List validators) { + List nonValidated = verifyAndGetNonValidated(validators, false); + if (!nonValidated.isEmpty()) { + JwsJsonProducer producer = new JwsJsonProducer(getDecodedJwsPayload()); + producer.getSignatureEntries().addAll(nonValidated); + return producer.getJwsJsonSignedDocument(); + } else { + return null; + } + } public boolean verifySignatureWith(JsonWebKey key) { return verifySignatureWith(JwsUtils.getSignatureVerifier(key)); } public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo) { return verifySignatureWith(JwsUtils.getSignatureVerifier(key, algo)); } - public JwsJsonProducer toProducer() { - JwsJsonProducer p = new JwsJsonProducer(getDecodedJwsPayload()); - p.getSignatureEntries().addAll(signatures); - return p; - } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/6ee6ff05/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java index b543ba7..642e2ce 100644 --- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java +++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java @@ -19,6 +19,7 @@ package org.apache.cxf.rs.security.jose.jws; import java.io.InputStream; +import java.util.Collections; import java.util.List; import org.apache.cxf.rs.security.jose.common.JoseConstants; @@ -87,6 +88,44 @@ public class JwsJsonConsumerTest extends Assert { assertNotNull(ecKey); assertTrue(sigEntries.get(1).verifySignatureWith(ecKey)); } + @Test + public void testVerifySingleEntryInDualSignedDocument() throws Exception { + JwsJsonConsumer consumer = new JwsJsonConsumer(DUAL_SIGNED_DOCUMENT); + JsonWebKeys jwks = readKeySet("jwkPublicJsonConsumerSet.txt"); + + List sigEntries = consumer.getSignatureEntries(); + assertEquals(2, sigEntries.size()); + // 1st signature + String firstKid = (String)sigEntries.get(0).getKeyId(); + assertEquals(KID_OF_THE_FIRST_SIGNER, firstKid); + JsonWebKey rsaKey = jwks.getKey(firstKid); + assertNotNull(rsaKey); + JwsSignatureVerifier jws = JwsUtils.getSignatureVerifier(rsaKey); + assertTrue(consumer.verifySignatureWith(jws)); + List remainingEntries = + consumer.verifyAndGetNonValidated(Collections.singletonList(jws)); + assertEquals(1, remainingEntries.size()); + assertEquals(KID_OF_THE_SECOND_SIGNER, remainingEntries.get(0).getKeyId()); + + } + + @Test(expected = JwsException.class) + public void testFailVerifyAllWithSingleValidator() throws Exception { + JwsJsonConsumer consumer = new JwsJsonConsumer(DUAL_SIGNED_DOCUMENT); + JsonWebKeys jwks = readKeySet("jwkPublicJsonConsumerSet.txt"); + + List sigEntries = consumer.getSignatureEntries(); + assertEquals(2, sigEntries.size()); + // 1st signature + String firstKid = (String)sigEntries.get(0).getKeyId(); + assertEquals(KID_OF_THE_FIRST_SIGNER, firstKid); + JsonWebKey rsaKey = jwks.getKey(firstKid); + assertNotNull(rsaKey); + JwsSignatureVerifier jws = JwsUtils.getSignatureVerifier(rsaKey); + assertTrue(consumer.verifySignatureWith(jws)); + consumer.verifyAndGetNonValidated(Collections.singletonList(jws), true); + fail(); + } public JsonWebKeys readKeySet(String fileName) throws Exception { InputStream is = JwsJsonConsumerTest.class.getResourceAsStream(fileName); return JwkUtils.readJwkSet(is);