/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.urlsigning.utils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.opencastproject.urlsigning.common.Policy; import org.opencastproject.urlsigning.common.ResourceRequest; import org.opencastproject.urlsigning.common.ResourceRequest.Status; import org.apache.http.NameValuePair; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.Before; import org.junit.Test; import java.net.URI; import java.net.URISyntaxException; import java.util.List; import java.util.Properties; public class ResourceRequestUtilTest { private static final String keyId = "default"; private static final String key = "0123456789abcdef"; private static final String clientIp = "10.0.0.1"; private Properties properties; @Before public void setUp() { properties = new Properties(); properties.put(keyId, key); } @Test public void testQueryStringParsing() { String policyValue = "{policy:'value'}"; String signatureValue = "randomString"; String queryString = "?" + ResourceRequest.POLICY_KEY + "=" + policyValue + "&" + ResourceRequest.SIGNATURE_KEY + "=" + signatureValue + "&" + ResourceRequest.ENCRYPTION_ID_KEY + "=" + keyId; List<NameValuePair> parameters = ResourceRequestUtil.parseQueryString(queryString); boolean foundOrg = false; boolean foundPolicy = false; boolean foundSignature = false; for (NameValuePair nameValuePair : parameters) { if (ResourceRequest.ENCRYPTION_ID_KEY.equals(nameValuePair.getName())) { assertEquals(keyId, nameValuePair.getValue()); foundOrg = true; } if (ResourceRequest.POLICY_KEY.equals(nameValuePair.getName())) { assertEquals(policyValue, nameValuePair.getValue()); foundPolicy = true; } if (ResourceRequest.SIGNATURE_KEY.equals(nameValuePair.getName())) { assertEquals(signatureValue, nameValuePair.getValue()); foundSignature = true; } } assertTrue("Didn't find the organization value.", foundOrg); assertTrue("Didn't find the policy value.", foundPolicy); assertTrue("Didn't find the signature value.", foundSignature); } @Test public void testAuthenticateDuplicateProperties() { // Test duplicate query properties. String twoOrgs = ResourceRequest.ENCRYPTION_ID_KEY + "=org1&" + ResourceRequest.ENCRYPTION_ID_KEY + "=org2"; assertEquals(Status.BadRequest, ResourceRequestUtil.resourceRequestFromQueryString(twoOrgs, clientIp, null, properties, true).getStatus()); String twoPolicies = ResourceRequest.POLICY_KEY + "=policy1&" + ResourceRequest.POLICY_KEY + "=policy2"; assertEquals(Status.BadRequest, ResourceRequestUtil .resourceRequestFromQueryString(twoPolicies, clientIp, null, properties, true).getStatus()); String twoSignatures = ResourceRequest.SIGNATURE_KEY + "=signature1&" + ResourceRequest.SIGNATURE_KEY + "=signature1"; assertEquals(Status.BadRequest, ResourceRequestUtil .resourceRequestFromQueryString(twoSignatures, clientIp, null, properties, true).getStatus()); } @Test public void testAuthenticateMissingProperties() { // Test Missing query properties String missingOrg = ResourceRequest.POLICY_KEY + "=policy&" + ResourceRequest.SIGNATURE_KEY + "=signature"; assertEquals(Status.BadRequest, ResourceRequestUtil .resourceRequestFromQueryString(missingOrg, clientIp, null, properties, true).getStatus()); String missingPolicy = ResourceRequest.ENCRYPTION_ID_KEY + "=organization&" + ResourceRequest.SIGNATURE_KEY + "=signature"; assertEquals(Status.BadRequest, ResourceRequestUtil .resourceRequestFromQueryString(missingPolicy, clientIp, null, properties, true).getStatus()); String missingSignature = ResourceRequest.ENCRYPTION_ID_KEY + "=organization&" + ResourceRequest.POLICY_KEY + "=policy"; assertEquals(Status.BadRequest, ResourceRequestUtil .resourceRequestFromQueryString(missingSignature, clientIp, null, properties, true).getStatus()); } @Test public void testAuthenticatePolicyMatchesSignature() throws Exception { DateTime after = new DateTime(DateTimeZone.UTC); after = after.minus(2 * 60 * 60 * 1000L); DateTime before = new DateTime(DateTimeZone.UTC); before = before.plus(2 * 60 * 60 * 1000L); String nonMatchingResource = "http://other.com"; Policy nonMatchingPolicy = Policy.mkSimplePolicy(nonMatchingResource, before); String matchingResource = "http://mh-allinone/"; Policy matchingPolicy = Policy.mkSimplePolicy(matchingResource, before); String signature = PolicyUtils.getPolicySignature(matchingPolicy, key); // Test non-existant encryption key is forbidden. String wrongEncryptionKeyId = ResourceRequest.ENCRYPTION_ID_KEY + "=" + "WrongId" + "&" + ResourceRequest.POLICY_KEY + "=" + PolicyUtils.toBase64EncodedPolicy(matchingPolicy) + "&" + ResourceRequest.SIGNATURE_KEY + "=" + signature; assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(wrongEncryptionKeyId, clientIp, matchingResource, properties, true) .getStatus()); // Test non matching resource results is forbidden. String nonMatching = ResourceRequest.ENCRYPTION_ID_KEY + "=organization&" + ResourceRequest.POLICY_KEY + "=" + PolicyUtils.toBase64EncodedPolicy(nonMatchingPolicy) + "&" + ResourceRequest.SIGNATURE_KEY + "=" + signature; assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(nonMatching, clientIp, matchingResource, properties, true).getStatus()); // Test non-matching client ip results in forbidden. Policy wrongClientPolicy = Policy.mkPolicyValidWithIP(matchingResource, before, "10.0.0.255"); String wrongClient = ResourceRequestUtil.policyToResourceRequestQueryString(wrongClientPolicy, keyId, key); assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(wrongClient, clientIp, matchingResource, properties, true).getStatus()); // Test matching client ip results in ok. Policy rightClientPolicy = Policy.mkPolicyValidWithIP(matchingResource, before, clientIp); String rightClient = ResourceRequestUtil.policyToResourceRequestQueryString(rightClientPolicy, keyId, key); assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(rightClient, clientIp, matchingResource, properties, true).getStatus()); // Test not yet DateGreaterThan results in gone Policy wrongDateGreaterThanPolicy = Policy.mkPolicyValidFrom(matchingResource, before, before); String wrongDateGreaterThan = ResourceRequestUtil.policyToResourceRequestQueryString(wrongDateGreaterThanPolicy, keyId, key); assertEquals(Status.Gone, ResourceRequestUtil .resourceRequestFromQueryString(wrongDateGreaterThan, clientIp, matchingResource, properties, true) .getStatus()); // Test after DateGreaterThan results in ok Policy rightDateGreaterThanPolicy = Policy.mkPolicyValidFrom(matchingResource, before, after); String rightDateGreaterThan = ResourceRequestUtil.policyToResourceRequestQueryString(rightDateGreaterThanPolicy, keyId, key); assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(rightDateGreaterThan, clientIp, matchingResource, properties, true) .getStatus()); // Test before DateLessThan results in gone Policy wrongDateLessThanPolicy = Policy.mkSimplePolicy(matchingResource, after); String wrongDateLessThan = ResourceRequestUtil.policyToResourceRequestQueryString(wrongDateLessThanPolicy, keyId, key); assertEquals(Status.Gone, ResourceRequestUtil .resourceRequestFromQueryString(wrongDateLessThan, clientIp, matchingResource, properties, true) .getStatus()); // Test matching results in ok. String matching = ResourceRequest.ENCRYPTION_ID_KEY + "=" + keyId + "&" + ResourceRequest.POLICY_KEY + "=" + PolicyUtils.toBase64EncodedPolicy(matchingPolicy) + "&" + ResourceRequest.SIGNATURE_KEY + "=" + signature; assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(matching, clientIp, matchingResource, properties, true).getStatus()); } @Test public void testIsSigned() throws URISyntaxException { String noQueryString = "http://notsigned.com"; String wrongQueryString = "http://notsigned.com?irrelevant=value"; String signed = "http://notsigned.com?signature=theSignature&keyId=theKey&policy=thePolicy"; assertFalse(ResourceRequestUtil.isSigned(new URI(noQueryString))); assertFalse(ResourceRequestUtil.isSigned(new URI(wrongQueryString))); assertTrue(ResourceRequestUtil.isSigned(new URI(signed))); } @Test public void testNonStrictResourceChecking() throws Exception { DateTime before = new DateTime(DateTimeZone.UTC); before = before.plus(2 * 60 * 60 * 1000L); String hostname = "signed.host.com"; String path = "/path/to/resource"; String rtmpResource = "rtmp://" + hostname + path; String httpResource = "http://" + hostname + path; String portResource = "rtmp://" + hostname + ":8080" + path; String differentHostnameResource = "rtmp://different.host.com" + path; Policy differentScheme = Policy.mkSimplePolicy(rtmpResource, before); String signature = PolicyUtils.getPolicySignature(differentScheme, key); String differentSchemeQueryString = ResourceRequest.ENCRYPTION_ID_KEY + "=default&" + ResourceRequest.POLICY_KEY + "=" + PolicyUtils.toBase64EncodedPolicy(differentScheme) + "&" + ResourceRequest.SIGNATURE_KEY + "=" + signature; assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, httpResource, properties, false).getStatus()); assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, httpResource, properties, true).getStatus()); assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, portResource, properties, false).getStatus()); assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, portResource, properties, true).getStatus()); assertEquals(Status.Ok, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, differentHostnameResource, properties, false).getStatus()); assertEquals(Status.Forbidden, ResourceRequestUtil .resourceRequestFromQueryString(differentSchemeQueryString, clientIp, differentHostnameResource, properties, true).getStatus()); } }