ResourceRequestUtil { public static ResourceRequest resourceRequestFromQueryString(String queryString, String clientIp, String resourceUri, Properties encryptionKeys, boolean strict) { ResourceRequest resourceRequest = new ResourceRequest(); List<NameValuePair> queryParameters = parseQueryString(queryString); if (!getQueryStringParameters(resourceRequest, queryParameters)) { return resourceRequest; } String encryptionKey = encryptionKeys.getProperty(resourceRequest.getEncryptionKeyId()); if (StringUtils.isBlank(encryptionKey)) { resourceRequest.setStatus(Status.Forbidden); resourceRequest .setRejectionReason(String.format("Forbidden because unable to find an encryption key with ID '%s'.", resourceRequest.getEncryptionKeyId())); return resourceRequest; } Policy policy = PolicyUtils.fromBase64EncodedPolicy(resourceRequest.getEncodedPolicy()); resourceRequest.setPolicy(policy); if (!policyMatchesSignature(policy, resourceRequest.getSignature(), encryptionKey)) { resourceRequest.setStatus(Status.Forbidden); try { String policySignature = PolicyUtils.getPolicySignature(policy, encryptionKey); resourceRequest .setRejectionReason(String .format("Forbidden because policy and signature do not match. Policy: '%s' created Signature from this policy '%s' and query string Signature: '%s'.", PolicyUtils.toJson(resourceRequest.getPolicy()).toJSONString(), policySignature, resourceRequest.getSignature())); } catch (Exception e) { resourceRequest .setRejectionReason(String .format("Forbidden because policy and signature do not match. Policy: '%s' and query string Signature: '%s'. Unable to sign policy because: %s", PolicyUtils.toJson(resourceRequest.getPolicy()).toJSONString(), resourceRequest.getSignature(), ExceptionUtils.getStackTrace(e))); } return resourceRequest; } if (policy.getClientIpAddress().isPresent() && !policy.getClientIpAddress().get().getHostAddress().equalsIgnoreCase(clientIp)) { resourceRequest.setStatus(Status.Forbidden); resourceRequest.setRejectionReason(String.format( "Forbidden because client trying to access the resource '%s' doesn't match the policy client '%s'", clientIp, resourceRequest.getPolicy().getClientIpAddress())); return resourceRequest; } if (strict && !policy.getResource().equals(resourceUri)) { resourceRequest.setStatus(Status.Forbidden); resourceRequest.setRejectionReason(String.format( "Forbidden because resource trying to be accessed '%s' doesn't match policy resource '%s'", resourceUri, resourceRequest.getPolicy().getBaseUrl())); return resourceRequest; } else if (!strict) { try { String requestedPath = new URI(resourceUri).getPath(); String policyPath = new URI(policy.getResource()).getPath(); if (!policyPath.endsWith(requestedPath)) { resourceRequest.setStatus(Status.Forbidden); resourceRequest.setRejectionReason(String.format( "Forbidden because resource trying to be accessed '%s' doesn't match policy resource '%s'", resourceUri, resourceRequest.getPolicy().getBaseUrl())); return resourceRequest; } } catch (URISyntaxException e) { resourceRequest.setStatus(Status.Forbidden); resourceRequest .setRejectionReason(String .format("Forbidden because either the policy or requested URI cannot be parsed. Policy Path: '%s' and Request Path: '%s'. Unable to sign policy because: %s", policy.getResource(), resourceUri, ExceptionUtils.getStackTrace(e))); return resourceRequest; } } if (new DateTime(DateTimeZone.UTC).isAfter(policy.getValidUntil().getMillis())) { resourceRequest.setStatus(Status.Gone); resourceRequest.setRejectionReason( String.format("The resource is gone because now '%s' is after the expiry time of '%s'", humanReadableFormat.print(new DateTime(DateTimeZone.UTC)), humanReadableFormat.print(new DateTime(policy.getValidUntil().getMillis(), DateTimeZone.UTC)))); return resourceRequest; } if (policy.getValidFrom().isPresent() && new DateTime(DateTimeZone.UTC).isBefore(policy.getValidFrom().get().getMillis())) { resourceRequest.setStatus(Status.Gone); resourceRequest.setRejectionReason( String.format("The resource is gone because now '%s' is before the available time of ", humanReadableFormat.print(new DateTime(DateTimeZone.UTC)), humanReadableFormat.print(policy.getValidFrom().get()))); return resourceRequest; } resourceRequest.setStatus(Status.Ok); return resourceRequest; } private  ResourceRequestUtil(); static String policyToResourceRequestQueryString(Policy policy, String encryptionKeyId, String encryptionKey); static String resourceRequestToQueryString(ResourceRequest resourceRequest); static ResourceRequest resourceRequestFromQueryString(String queryString, String clientIp, String resourceUri,
          Properties encryptionKeys, boolean strict); static boolean isNotSigned(URI uri); static boolean isSigned(URI uri);  }
@Test public void testAuthenticateDuplicateProperties() { 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() { 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 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: String httpResource = "http: String portResource = "rtmp: String differentHostnameResource = "rtmp: 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()); }