Author: ieb
Date: Fri Aug 16 11:31:25 2013
New Revision: 1514660

URL: http://svn.apache.org/r1514660
Log:
refactored to cover just request signing, ignoring responses signing.

Added:
    
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java
   (with props)
    
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java
   (with props)
    
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java
   (with props)
Removed:
    
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/SealedResponse.java
    
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/SealingFilter.java

Added: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java?rev=1514660&view=auto
==============================================================================
--- 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java
 (added)
+++ 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java
 Fri Aug 16 11:31:25 2013
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The SF licenses this file
+ * to you under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.sling.sealed;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+
+@Service(value = Filter.class)
+@Component(immediate = true, metatype = true)
+@Properties(@Property(name = "path", value = "/sealed"))
+public class RequestHmacFilter implements Filter {
+
+    @Property(cardinality = Integer.MAX_VALUE)
+    private static final String PROP_PATTERNS = "sealed-paths";
+
+    private Pattern[] pathPatterns;
+
+    @Reference
+    private RequestHmacService sealer;
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Activate
+    public void activate(Map<String, Object> properties) {
+        pathPatterns = buildPatterns((String[]) properties.get(PROP_PATTERNS));
+    }
+
+    private Pattern[] buildPatterns(String[] patterns) {
+        if (patterns != null) {
+            Pattern[] p = new Pattern[patterns.length];
+            for (int i = 0; i < p.length; i++) {
+                p[i] = Pattern.compile(patterns[i]);
+            }
+            return p;
+        }
+        return new Pattern[0];
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain)
+            throws IOException, ServletException {
+        if (isSecure(request) && failsVerification(request)) {
+            ((HttpServletResponse) 
response).sendError(HttpServletResponse.SC_FORBIDDEN,
+                "Untrusted request");
+        } else {
+            chain.doFilter(request, response);
+        }
+    }
+
+    /**
+     * 
+     * @param request
+     * @return false if the request passes verification.
+     * @throws IOException
+     */
+    private boolean failsVerification(ServletRequest request) throws 
IOException {
+        if (request instanceof HttpServletRequest) {
+            HttpServletRequest hrequest = (HttpServletRequest) request;
+            return !sealer.verifyRequest(hrequest);
+        }
+        return false;
+    }
+
+    /**
+     * Should the request and response be secure and trusted ?
+     * 
+     * @param request
+     * @return
+     */
+    private boolean isSecure(ServletRequest request) {
+        if (sealer.isConfigured() && request instanceof HttpServletRequest) {
+            return match(((HttpServletRequest) request).getRequestURI(), 
pathPatterns);
+        }
+        return false;
+    }
+
+
+    /**
+     * return true if the test matches any of the patterns.
+     * 
+     * @param test
+     * @param patterns
+     * @return
+     */
+    private boolean match(String test, Pattern[] patterns) {
+        for (Pattern urls : patterns) {
+            if (urls.matcher(test).find()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void destroy() {
+    }
+
+}

Propchange: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java?rev=1514660&view=auto
==============================================================================
--- 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java
 (added)
+++ 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java
 Fri Aug 16 11:31:25 2013
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The SF licenses this file
+ * to you under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.sling.sealed;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Provides 
+ */
+public interface RequestHmacService {
+    
+    String X_SIG_HEADER = "x-sig";
+
+
+    /**
+     * @return true of the sealer implementation is configured.
+     */
+    boolean isConfigured();
+
+    /**
+     * @param hrequest the request to verify.
+     * @return true if valid.
+     */
+    boolean verifyRequest(HttpServletRequest hrequest);
+
+    /**
+     * Get a request hmac header  for a request URI, parameters and headers. 
Clients should set a
+     * request header with the name contained in the constant X_SIG_HEADER 
before sending the request.
+     * @param requestUri
+     * @param requestParams
+     * @param headers
+     * @return the request header that should be sent with the the request.
+     * @throws UnsupportedEncodingException
+     */
+    String getRequestHeader(String requestUri, Map<String, String[]> 
requestParams,
+            Map<String, String> headers) throws UnsupportedEncodingException;
+
+}

Propchange: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java?rev=1514660&view=auto
==============================================================================
--- 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java
 (added)
+++ 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java
 Fri Aug 16 11:31:25 2013
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The SF licenses this file
+ * to you under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.sling.sealed;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+@Component(immediate=true, metatype=true)
+@Service(value=RequestHmacService.class)
+public class RequestHmacServiceImpl implements RequestHmacService {
+
+    private static final String HMAC_ALG = "HmacSHA256";
+    
+    @Property(cardinality= Integer.MAX_VALUE)
+    private static final String PROP_HEADERNAMES = "sealed-headers";
+
+    @Property
+    private static final String PROP_SHARED_KEY = "shared-key";
+
+    
+    private String[] headerNames;
+
+    private Key key;
+
+
+
+    @Activate
+    public void activate(Map<String, Object> properties) {
+        headerNames = buildHeaderNames((String[]) 
properties.get(PROP_HEADERNAMES));
+        key = buildKey((String) properties.get(PROP_SHARED_KEY));
+    }
+
+
+    public boolean verifyRequest(HttpServletRequest hrequest) {
+        try {
+            return verifyHmac(buildRequestMessage(hrequest), 
hrequest.getHeader(X_SIG_HEADER));
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Get a hmac from a captured response.
+     * @param byteOutputStream
+     * @param headers
+     * @return
+     * @throws UnsupportedEncodingException
+     */
+    public String getRequestHeader(String requestUri, Map<String, String[]> 
requestParams, Map<String, String> headers)
+            throws UnsupportedEncodingException {
+        return doMac(buildRequestMesssage(requestUri, requestParams, headers));
+    }
+
+    private String buildRequestMesssage(String uri, Map<String, String[]> 
params, Map<String, String> headers)
+            throws UnsupportedEncodingException {
+        StringBuilder message = new StringBuilder(uri);
+        for (String headerName : headerNames) {
+            message.append(headers.get(headerName));
+        }        
+        List<String> orderedNames = new ArrayList<String>(params.keySet());
+        Collections.sort(orderedNames);
+        for (String n : orderedNames) {
+            message.append(n).append(Arrays.toString(params.get(n)));
+        }
+        return message.toString();
+    }
+
+    public boolean isConfigured() {
+        return (key != null);
+    }
+
+    /**
+     * Build a message from the request
+     * 
+     * @param request
+     * @return
+     * @throws IOException
+     */
+    private String buildRequestMessage(HttpServletRequest request) throws 
IOException {
+        Map<String, String> headers = new HashMap<String, String>();
+        for (String headerName : headerNames) {
+            String v = request.getHeader(headerName);
+            headers.put(headerName, v);
+        }        
+        return buildRequestMesssage(request.getRequestURI(), 
request.getParameterMap(), headers);
+    }
+
+    /**
+     * verify a message against a hmac.
+     * 
+     * @param message the message
+     * @param hmac the hmac
+     * @return true if the message hasn't been tampered with and the hmac was
+     *         created with the same key.
+     */
+    private boolean verifyHmac(String message, String hmac) {
+        String newMac = doMac(message);
+        return (hmac != null && newMac != null && !hmac.equals(newMac));
+    }
+
+    /**
+     * Perform a hmac on a message.
+     * 
+     * @param message the message
+     * @return the hmac of the message or null if the hmac cant be computed.
+     */
+    private String doMac(String message) {
+        try {
+            Mac mac = Mac.getInstance(HMAC_ALG);
+            mac.init(key);
+            return new 
String(Base64.encodeBase64(mac.doFinal(message.getBytes("UTF-8"))), "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+        } catch (IllegalStateException e) {
+        } catch (NoSuchAlgorithmException e) {
+        } catch (InvalidKeyException e) {
+        }
+        return null;
+    }
+
+    private Key buildKey(String sharedKey) {
+        if ( sharedKey != null ) { 
+            return new SecretKeySpec(sharedKey.getBytes(), HMAC_ALG);
+        }
+        return null;
+        
+    }
+    
+
+    private String[] buildHeaderNames(String[] names) {
+        if ( names != null ) {
+            return names;
+        }
+        return new String[0];
+    }
+
+
+
+
+
+}

Propchange: 
sling/whiteboard/ieb/sealed/src/main/java/org/apache/sling/sealed/RequestHmacServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to