Author: scottbw
Date: Tue Aug 14 18:38:09 2012
New Revision: 1373012

URL: http://svn.apache.org/viewvc?rev=1373012&view=rev
Log:
Implementation of the W3C Digital Signature spec for Widgets; see WOOKIE-139. 
Thanks to Pushpalanka Jayawardhana for the patch.

Added:
    
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/IDigitalSignatureProcessor.java
    
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadAuthorSignatureException.java
    
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadDistributorSignatureException.java
    
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/InsecuredWidgetContentException.java
    incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/
    
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DSNamespaceContext.java
    
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DigitalSignatureProcessor.java
    
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/xmldsig-core-schema.xsd
Modified:
    
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/W3CWidgetFactory.java
    
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
    incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
    incubator/wookie/trunk/src/widgetserver.properties

Added: 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/IDigitalSignatureProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/IDigitalSignatureProcessor.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/IDigitalSignatureProcessor.java
 (added)
+++ 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/IDigitalSignatureProcessor.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,25 @@
+/*
+ *  Licensed 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.wookie.w3c;
+
+import org.apache.wookie.w3c.exceptions.BadAuthorSignatureException;
+import org.apache.wookie.w3c.exceptions.BadDistributorSignatureException;
+import org.apache.wookie.w3c.exceptions.InsecuredWidgetContentException;
+
+public interface IDigitalSignatureProcessor {
+  void processDigitalSignatures(String packagePath)
+      throws BadAuthorSignatureException, BadDistributorSignatureException,
+      InsecuredWidgetContentException;
+
+}

Modified: 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/W3CWidgetFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/W3CWidgetFactory.java?rev=1373012&r1=1373011&r2=1373012&view=diff
==============================================================================
--- 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/W3CWidgetFactory.java
 (original)
+++ 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/W3CWidgetFactory.java
 Tue Aug 14 18:38:09 2012
@@ -27,6 +27,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
 import org.apache.wookie.w3c.exceptions.BadManifestException;
 import org.apache.wookie.w3c.exceptions.BadWidgetZipFileException;
+import org.apache.wookie.w3c.exceptions.InsecuredWidgetContentException;
 import org.apache.wookie.w3c.exceptions.InvalidContentTypeException;
 import org.apache.wookie.w3c.exceptions.InvalidStartFileException;
 import org.apache.wookie.w3c.impl.WidgetManifestModel;
@@ -72,7 +73,9 @@ public class W3CWidgetFactory {
        private File unzippedWidgetDirectory;
        private File outputDirectory;
        private IStartPageProcessor startPageProcessor;
-       private String[] locales;
+       private IDigitalSignatureProcessor digitalSignatureParser;
+
+  private String[] locales;
        private String localPath;
        private String[] features;
        private String[] encodings;
@@ -121,6 +124,10 @@ public class W3CWidgetFactory {
        public void setStartPageProcessor(final IStartPageProcessor 
startPageProcessor) {
                this.startPageProcessor = startPageProcessor;
        }
+       
+    public void setDigitalSignatureParser(IDigitalSignatureProcessor 
digitalSignatureParser) {
+        this.digitalSignatureParser = digitalSignatureParser;
+    }
 
        /**
         * Set the supported locales to be used when parsing widgets
@@ -256,7 +263,8 @@ public class W3CWidgetFactory {
         * @throws BadWidgetZipFileException
         * @throws BadManifestException
         */
-       private W3CWidget processWidgetPackage(File zipFile, String 
defaultIdentifier) throws BadWidgetZipFileException, BadManifestException{
+       private W3CWidget processWidgetPackage(File zipFile, String 
defaultIdentifier) throws BadWidgetZipFileException,
+                       BadManifestException, InsecuredWidgetContentException {
          ZipFile zip;
                try {
                        zip = new ZipFile(zipFile);
@@ -273,8 +281,13 @@ public class W3CWidgetFactory {
                                // create the folder structure to unzip the zip 
into
                                unzippedWidgetDirectory = 
WidgetPackageUtils.createUnpackedWidgetFolder(outputDirectory, 
manifestIdentifier);
                                // now unzip it into that folder
-                               WidgetPackageUtils.unpackZip(zip, 
unzippedWidgetDirectory);     
-                               
+        WidgetPackageUtils.unpackZip(zip, unzippedWidgetDirectory);
+        // checks for validity of widget using digital signatures
+        if (digitalSignatureParser != null) {
+          digitalSignatureParser
+              .processDigitalSignatures(unzippedWidgetDirectory
+                  .getAbsolutePath());
+        }
                                // Iterate over all start files and update paths
                                for (IContent content: 
widgetModel.getContentList()){
                                        // now update the js links in the start 
page
@@ -283,7 +296,7 @@ public class W3CWidgetFactory {
                                        content.setSrc(relativestartUrl);
                                        if(startFile.exists() && 
startPageProcessor != null){           
                                                
startPageProcessor.processStartFile(startFile, widgetModel, content);
-                                       }       
+                                       }
                                }
                                if (widgetModel.getContentList().isEmpty()){
                                        throw new 
InvalidStartFileException("Widget has no start page");
@@ -292,11 +305,14 @@ public class W3CWidgetFactory {
                                // get the path to the root of the unzipped 
folder
                                String thelocalPath = 
WidgetPackageUtils.getURLForWidget(localPath, manifestIdentifier, "");
                                // now pass this to the model which will 
prepend the path to local resources (not web icons)
-                               widgetModel.updateIconPaths(thelocalPath);      
                        
+                               widgetModel.updateIconPaths(thelocalPath);
                                
                                // check to see if this widget already exists 
in the DB - using the ID (guid) key from the manifest
                                return widgetModel;
-                       } catch (InvalidStartFileException e) {
+
+                       }catch(InsecuredWidgetContentException ex){
+                               throw ex;
+                       }catch (InvalidStartFileException e) {
                                throw e;
                        } catch (BadManifestException e) {
                                throw e;

Added: 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadAuthorSignatureException.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadAuthorSignatureException.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadAuthorSignatureException.java
 (added)
+++ 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadAuthorSignatureException.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,23 @@
+/*
+ *  Licensed 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.wookie.w3c.exceptions;
+
+public class BadAuthorSignatureException extends Exception {
+
+    private static final long serialVersionUID = 3618329424580818921L;
+
+    public BadAuthorSignatureException(String message) {
+        super(message);
+    }
+}

Added: 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadDistributorSignatureException.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadDistributorSignatureException.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadDistributorSignatureException.java
 (added)
+++ 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/BadDistributorSignatureException.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,24 @@
+/*
+ *  Licensed 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.wookie.w3c.exceptions;
+
+public class BadDistributorSignatureException extends Exception {
+
+    private static final long serialVersionUID = -1889409740023396757L;
+    
+    public BadDistributorSignatureException(String message) {
+        super(message);
+    }
+
+}
\ No newline at end of file

Added: 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/InsecuredWidgetContentException.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/InsecuredWidgetContentException.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/InsecuredWidgetContentException.java
 (added)
+++ 
incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/exceptions/InsecuredWidgetContentException.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,23 @@
+/*
+ *  Licensed 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.wookie.w3c.exceptions;
+
+public class InsecuredWidgetContentException extends Exception {
+
+       private static final long serialVersionUID = -3335092648062748129L;
+
+       public InsecuredWidgetContentException(String message) {
+               super(message);
+       }
+}

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java?rev=1373012&r1=1373011&r2=1373012&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java 
(original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/controller/WidgetsController.java 
Tue Aug 14 18:38:09 2012
@@ -19,6 +19,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.security.KeyStore;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -42,6 +43,7 @@ import org.apache.wookie.server.LocaleHa
 import org.apache.wookie.util.NewWidgetBroadcaster;
 import org.apache.wookie.util.WidgetFileUtils;
 import org.apache.wookie.util.WidgetJavascriptSyntaxAnalyzer;
+import org.apache.wookie.util.digitalsignature.DigitalSignatureProcessor;
 import org.apache.wookie.util.gadgets.GadgetUtils;
 import org.apache.wookie.util.html.StartPageProcessor;
 import org.apache.wookie.w3c.W3CWidget;
@@ -225,7 +227,12 @@ public class WidgetsController extends C
     Configuration properties = (Configuration) 
getServletContext().getAttribute("properties"); //$NON-NLS-1$
     final String WIDGETFOLDER = 
getServletContext().getRealPath(properties.getString("widget.widgetfolder"));//$NON-NLS-1$
     final String UPLOADFOLDER = 
getServletContext().getRealPath(properties.getString("widget.useruploadfolder"));//$NON-NLS-1$
-
+       // Digital signature settings
+    final boolean VERIFYSIGNATURE = 
properties.getBoolean("widget.deployment.verifysignature");//$NON-NLS-1$
+    final boolean REJECTINVALID= 
properties.getBoolean("widget.deployment.rejectinvalidsignatures");
+    final boolean REJECTUNTRUSTED= 
properties.getBoolean("widget.deployment.rejectuntrustedsignatures");
+    final String PASSWORD = 
properties.getString("widget.deployment.trustedkeystore.password");
+    final String KEYSTORE = 
properties.getString("widget.deployment.trustedkeystore");//$NON-NLS-1$
     //
     // Get localized messages so we can return errors
     //
@@ -260,7 +267,16 @@ public class WidgetsController extends C
         fac.setOutputDirectory(WIDGETFOLDER);
         fac.setFeatures(Features.getFeatureNames());
         fac.setStartPageProcessor(new StartPageProcessor());
-        W3CWidget widgetModel = fac.parse(zipFile);
+        if (VERIFYSIGNATURE) {
+        InputStream stream = getServletContext().getResourceAsStream(
+            "/WEB-INF/classes/" + KEYSTORE);
+        KeyStore keyStore = KeyStore.getInstance("JKS");
+        keyStore.load(stream, PASSWORD.toCharArray());
+        stream.close();
+        fac.setDigitalSignatureParser(new DigitalSignatureProcessor(keyStore,
+            REJECTINVALID, REJECTUNTRUSTED));
+      }
+       W3CWidget widgetModel = fac.parse(zipFile);
         new WidgetJavascriptSyntaxAnalyzer(fac.getUnzippedWidgetDirectory());
        // File f = new File();
         //

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java?rev=1373012&r1=1373011&r2=1373012&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java 
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java 
Tue Aug 14 18:38:09 2012
@@ -16,6 +16,8 @@ package org.apache.wookie.server;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
 import java.util.Iterator;
 import java.util.Locale;
 
@@ -23,27 +25,28 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 
+import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.log4j.Logger;
 import org.apache.wookie.Messages;
 import org.apache.wookie.beans.util.IPersistenceManager;
 import org.apache.wookie.beans.util.PersistenceManagerFactory;
 import org.apache.wookie.feature.Features;
-import org.apache.wookie.helpers.WidgetRuntimeHelper;
 import org.apache.wookie.helpers.WidgetFactory;
+import org.apache.wookie.helpers.WidgetRuntimeHelper;
 import org.apache.wookie.util.NewWidgetBroadcaster;
 import org.apache.wookie.util.WgtWatcher;
 import org.apache.wookie.util.WidgetFileUtils;
 import org.apache.wookie.util.WidgetJavascriptSyntaxAnalyzer;
+import org.apache.wookie.util.digitalsignature.DigitalSignatureProcessor;
 import org.apache.wookie.util.html.StartPageProcessor;
+import org.apache.wookie.w3c.W3CWidget;
 import org.apache.wookie.w3c.W3CWidgetFactory;
 import org.apache.wookie.w3c.exceptions.BadManifestException;
 import org.apache.wookie.w3c.exceptions.BadWidgetZipFileException;
 import org.apache.wookie.w3c.util.WidgetPackageUtils;
-import org.apache.wookie.w3c.W3CWidget;
 
 /**
  * ContextListener - does some init work and makes certain things are 
available 
@@ -68,7 +71,7 @@ public class ContextListener implements 
     public void contextInitialized(ServletContextEvent event) {
                try {
                        ServletContext context = event.getServletContext();
-                       
WidgetRuntimeHelper.setWebContextPath(context.getContextPath());                
        
+                       
WidgetRuntimeHelper.setWebContextPath(context.getContextPath());
                        /* 
                         *  load the widgetserver.properties and 
local.widget.properties file
                         *  and put it into this context as an attribute 
'properties' available to all resources
@@ -157,7 +160,7 @@ public class ContextListener implements 
         * @param context the current servlet context
         * @param configuration the configuration properties
         */
-       private void startWatcher(ServletContext context, final Configuration 
configuration, final Messages localizedMessages){
+       private void startWatcher(final ServletContext context, final 
Configuration configuration, final Messages localizedMessages){
                /*
                 * Start watching for widget deployment
                 */
@@ -167,6 +170,14 @@ public class ContextListener implements 
                final String localWidgetFolderPath = 
configuration.getString("widget.widgetfolder");
                final String[] locales = 
configuration.getStringArray("widget.locales");
                final String contextPath = context.getContextPath();
+               // Digital signature settings
+           final boolean VERIFYSIGNATURE = 
configuration.getBoolean("widget.deployment.verifysignature");//$NON-NLS-1$
+               final boolean REJECTINVALID= 
configuration.getBoolean("widget.deployment.rejectinvalidsignatures");
+               final boolean REJECTUNTRUSTED= 
configuration.getBoolean("widget.deployment.rejectuntrustedsignatures");
+               final String PASSWORD = 
configuration.getString("widget.deployment.trustedkeystore.password");
+           final String KEYSTORE = 
configuration.getString("widget.deployment.trustedkeystore");//$NON-NLS-1$
+
+
                Thread thr = new Thread(){
                        public void run() {
                                int interval = 5000;
@@ -185,6 +196,16 @@ public class ContextListener implements 
                                                        
fac.setOutputDirectory(WIDGETFOLDER);
                                                        
fac.setFeatures(Features.getFeatureNames());
                                                        
fac.setStartPageProcessor(new StartPageProcessor());
+              if (VERIFYSIGNATURE) {
+                InputStream stream = context
+                    .getResourceAsStream("/WEB-INF/classes/" + KEYSTORE);
+                KeyStore keyStore = KeyStore.getInstance("JKS");
+                keyStore.load(stream, PASSWORD.toCharArray());
+                stream.close();
+                fac.setDigitalSignatureParser(new DigitalSignatureProcessor(
+                    keyStore, REJECTINVALID, REJECTUNTRUSTED));
+              }
+
                                                        W3CWidget model = 
fac.parse(upload);
                                                        
WidgetJavascriptSyntaxAnalyzer jsa = new 
WidgetJavascriptSyntaxAnalyzer(fac.getUnzippedWidgetDirectory());
                                                        
if(persistenceManager.findWidgetByGuid(model.getIdentifier()) == null) {

Added: 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DSNamespaceContext.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DSNamespaceContext.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DSNamespaceContext.java
 (added)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DSNamespaceContext.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,54 @@
+/**
+ * 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 ASF 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.wookie.util.digitalsignature;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+
+
+/** A NamespaceContext implementation for digital signatures */
+public class DSNamespaceContext implements NamespaceContext {
+
+  private Map<String, String> namespaceMap = new HashMap<String, String>();
+
+  public DSNamespaceContext() {
+    namespaceMap.put("ds", "http://www.w3.org/2000/09/xmldsig#";);
+  }
+
+  public String getNamespaceURI(String arg0) {
+    return namespaceMap.get(arg0);
+  }
+
+  public String getPrefix(String arg0) {
+    for (String key : namespaceMap.keySet()) {
+      String value = namespaceMap.get(key);
+      if (value.equals(arg0)) {
+        return key;
+      }
+    }
+    return null;
+  }
+
+  public Iterator<String> getPrefixes(String arg0) {
+    return namespaceMap.keySet().iterator();
+  }
+}

Added: 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DigitalSignatureProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DigitalSignatureProcessor.java?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DigitalSignatureProcessor.java
 (added)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/DigitalSignatureProcessor.java
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,414 @@
+/*
+ *  Licensed 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.wookie.util.digitalsignature;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.log4j.Logger;
+import org.apache.wookie.w3c.IDigitalSignatureProcessor;
+import org.apache.wookie.w3c.exceptions.BadAuthorSignatureException;
+import org.apache.wookie.w3c.exceptions.BadDistributorSignatureException;
+import org.apache.wookie.w3c.exceptions.InsecuredWidgetContentException;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.Element;
+
+/**
+ * verify widgets using digital signatures
+ * 
+ * @author Pushpalanka Jayawardhana
+ */
+public class DigitalSignatureProcessor implements IDigitalSignatureProcessor {
+
+  static {
+    org.apache.xml.security.Init.init();
+  }
+  static Logger _logger = Logger.getLogger(DigitalSignatureProcessor.class
+      .getName());
+
+  private KeyStore keystore;
+  // If true, Wookie will not deploy any widgets with invalid digital
+  // signatures. If set to false, the widget will be
+  // imported and a warning logged.
+  private boolean rejectInvalid;
+  // If true, Wookie will only deploy Widgets that have valid digital 
signatures
+  // AND that each signature uses a trusted
+  // certificate located in the trusted keystore.
+  private boolean rejectUntrusted;
+  private HashSet<String> filesList = new HashSet<String>();
+
+  public DigitalSignatureProcessor(KeyStore keyStore, boolean rejectInvalid,
+      boolean rejectUntrusted) {
+    this.keystore = keyStore;
+    this.rejectInvalid = rejectInvalid;
+    this.rejectUntrusted = rejectUntrusted;
+    // to make it default to reject invalid signatures if signatures with
+    // untrusted certificate are rejecting
+    if (rejectUntrusted) {
+      this.rejectInvalid = rejectUntrusted;
+    }
+  }
+
+  /**
+   * Process the signatures inside the widget to verify validity
+   * 
+   * @param packagePath
+   *          : widget package path
+   * @throws BadAuthorSignatureException
+   * @throws BadDistributorSignatureException
+   */
+  public void processDigitalSignatures(String packagePath)
+      throws BadAuthorSignatureException, BadDistributorSignatureException,
+      InsecuredWidgetContentException {
+
+    File widget = new File(packagePath);
+    File[] authorSignaturesList = locateAuthorSignatureFiles(widget);
+    File[] distributorSignaturesList = locateDistributorSignatureFiles(widget);
+    if ((authorSignaturesList.length == 0 && distributorSignaturesList.length 
== 0)
+        && rejectInvalid) {
+      throw new InsecuredWidgetContentException(
+          "Couldn't locate any signature file inside the widget "
+              + widget.getName());
+    } else if (authorSignaturesList.length == 0
+        && distributorSignaturesList.length == 0) {
+      _logger.warn("Couldn't locate any signature file inside the widget "
+          + widget.getName() + ", " + "but it will still be imported.");
+    } else {
+      verifyWidget(authorSignaturesList, distributorSignaturesList, widget);
+    }
+
+  }
+
+  /**
+   * Verify widgets to be deployed to be valid.
+   * 
+   * @param authorSignaturesList
+   *          : List of author signatures inside widget
+   * @param distributorSignaturesList
+   *          : List of distributor signatures inside widget
+   * @param widget
+   *          : to be deployed
+   * @return whether verified to be valid
+   * @throws BadAuthorSignatureException
+   * @throws BadDistributorSignatureException
+   */
+  private void verifyWidget(File[] authorSignaturesList,
+      File[] distributorSignaturesList, File widget)
+      throws BadAuthorSignatureException, BadDistributorSignatureException {
+    boolean isWidgetValid = false;
+
+    for (File file : authorSignaturesList) {
+      try {
+        isWidgetValid = isSignatureValid(file, "author", widget);
+        if ((!isWidgetValid) && rejectInvalid) {
+          throw new InsecuredWidgetContentException(
+              "Rejecting invalid author signature " + file.getName());
+        }
+        if (!isWidgetValid && !rejectInvalid) {
+          _logger.warn("The author signature \'" + file.getName()
+              + "\' is not valid, but widget will be imported");
+        }
+      } catch (Exception e) {
+        throw new BadAuthorSignatureException("Invalid Author Signature.");
+      }
+    }
+
+    for (File file : distributorSignaturesList) {
+      try {
+        isWidgetValid = isSignatureValid(file, "", widget);
+        if ((!isWidgetValid) && rejectInvalid) {
+          throw new InsecuredWidgetContentException(
+              "Rejecting invalid distributor signature " + file.getName());
+        }
+        if (!isWidgetValid && !rejectInvalid) {
+          _logger.warn("The distributor signature \'" + file.getName()
+              + "\' is not valid, but widget will be imported");
+        }
+      } catch (Exception e) {
+        throw new BadDistributorSignatureException(
+            "Invalid Distributor Signature " + file.getName());
+      }
+    }
+
+  }
+
+  /**
+   * Verify a signature file to be valid inside the widget folder.
+   * 
+   * @param file
+   *          : signature.xml file
+   * @param role
+   *          : role of the signer: Author/Distributor
+   * @param widget
+   *          : widget folder to be deployed
+   * @return whether signature file is valid inside the folder
+   * @throws Exception
+   */
+  private boolean isSignatureValid(File file, String role, File widget)
+      throws Exception {
+    boolean schemaValidate = true;
+    boolean isValid = false;
+    final String signatureSchemaFile = 
"src/org/apache/wookie/util/digitalsignature/xmldsig-core"
+        + "-schema.xsd";
+
+    if (schemaValidate) {
+      _logger.debug("Doing schema validation.");
+    }
+
+    javax.xml.parsers.DocumentBuilderFactory dbf = 
javax.xml.parsers.DocumentBuilderFactory
+        .newInstance();
+
+    if (schemaValidate) {
+      dbf.setAttribute("http://apache.org/xml/features/validation/schema";,
+          Boolean.TRUE);
+      dbf.setAttribute(
+          "http://apache.org/xml/features/dom/defer-node-expansion";,
+          Boolean.TRUE);
+      dbf.setValidating(true);
+      dbf.setAttribute("http://xml.org/sax/features/validation";, Boolean.TRUE);
+    }
+
+    dbf.setNamespaceAware(true);
+    dbf.setAttribute("http://xml.org/sax/features/namespaces";, Boolean.TRUE);
+
+    if (schemaValidate) {
+      dbf.setAttribute(
+          "http://apache.org/xml/properties/schema/external-schemaLocation";,
+          Constants.SignatureSpecNS + " " + signatureSchemaFile);
+    }
+
+    _logger.info("Trying to verify " + file.toURI().toURL().toString());
+
+    javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
+
+    db.setErrorHandler(new 
org.apache.xml.security.utils.IgnoreAllErrorHandler());
+
+    if (schemaValidate) {
+      db.setEntityResolver(new org.xml.sax.EntityResolver() {
+
+        public org.xml.sax.InputSource resolveEntity(String publicId,
+            String systemId) throws org.xml.sax.SAXException {
+
+          if (systemId.endsWith("xmldsig-core-schema.xsd")) {
+            try {
+              return new org.xml.sax.InputSource(new FileInputStream(
+                  signatureSchemaFile));
+            } catch (FileNotFoundException ex) {
+              throw new org.xml.sax.SAXException(ex);
+            }
+          } else {
+            return null;
+          }
+        }
+      });
+    }
+
+    org.w3c.dom.Document doc = db.parse(new java.io.FileInputStream(file));
+
+    XPathFactory xpf = XPathFactory.newInstance();
+    XPath xpath = xpf.newXPath();
+    xpath.setNamespaceContext(new DSNamespaceContext());
+
+    String expression = "//ds:Signature[1]";
+    Element sigElement = (Element) xpath.evaluate(expression, doc,
+        XPathConstants.NODE);
+    XMLSignature signature = new XMLSignature(sigElement, file.toURI().toURL()
+        .toString());
+    if (!isAllContentSigned(signature, role, widget)) {
+      return false;
+    } else {
+      KeyInfo ki = signature.getKeyInfo();
+
+      if (ki != null) {
+        if (ki.containsX509Data()) {
+          _logger.debug("Could find a X509Data element in the KeyInfo");
+        }
+
+        X509Certificate cert = signature.getKeyInfo().getX509Certificate();
+        if (!isTrusted(cert) && (rejectUntrusted)) {
+          _logger.error("Untrusted certificate submitted with the signature.");
+          throw new InsecuredWidgetContentException(
+              "Untrusted certificate submitted with the signature.");
+        }
+
+        if (cert != null) {
+          isValid = signature.checkSignatureValue(cert);
+          _logger.debug("The XML signature in file "
+              + file.toURI().toURL().toString() + " is "
+              + (isValid ? "valid! " : "invalid! "));
+        } else {
+          _logger.debug("Did not find a Certificate");
+
+          PublicKey pk = signature.getKeyInfo().getPublicKey();
+
+          if (pk != null) {
+            _logger.debug("The XML signature in file "
+                + file.toURI().toURL().toString() + " is "
+                + (signature.checkSignatureValue(pk) ? "valid!" : 
"invalid!)"));
+          } else {
+            _logger
+                .debug("Did not find a public key, so can't check the 
signature");
+          }
+        }
+      } else {
+        _logger.debug("Did not find a KeyInfo");
+      }
+    }
+    return isValid;
+  }
+
+  /**
+   * Make a list of author signatures present(According to the W3C spec there 
is
+   * only one author signature inside a widget folder)
+   * 
+   * @param widget
+   * @return
+   */
+  public File[] locateAuthorSignatureFiles(File widget) {
+
+    return widget.listFiles(new FilenameFilter() {
+      public boolean accept(File dir, String name) {
+        return name.contains("author") && name.contains("signature");
+      }
+    });
+  }
+
+  /**
+   * Make a list of distributor signatures present
+   * 
+   * @param widget
+   * @return
+   */
+  private File[] locateDistributorSignatureFiles(File widget) {
+    File[] files = widget.listFiles(new FilenameFilter() {
+      public boolean accept(File dir, String name) {
+        return (!name.contains("author")) && name.contains("signature");
+      }
+    });
+    return files;
+  }
+
+  /**
+   * Check whether all the content inside the widget folder is signed.If any
+   * additions are present except for that are referenced inside the signature,
+   * it is considered an invalid widget. Anyway inclusion of signature files is
+   * handled according to W3C widget digsig spec
+   * 
+   * @param signature
+   *          : validating signature file
+   * @param role
+   *          : role of the signer who generated the signature
+   * @param widget
+   *          : widget folder that is under verification
+   * @return : whether all the content is signed
+   * @throws org.apache.xml.security.exceptions.XMLSecurityException
+   */
+  private boolean isAllContentSigned(XMLSignature signature, final String role,
+      File widget) throws XMLSecurityException {
+    boolean isAllSigned = false;
+    HashSet<String> signedFiles = new HashSet<String>();
+    for (int i = 0; i < signature.getSignedInfo().getSignedContentLength() - 
1; i++) {
+      String[] filName = signature.getSignedInfo()
+          .getReferencedContentAfterTransformsItem(i).getSourceURI()
+          .split(File.separator);
+      signedFiles.add(filName[filName.length - 1]);
+    }
+
+    HashSet<String> widgetFilesList = new HashSet<String>(listFilesForFolder(
+        widget, role));
+    filesList.clear();
+
+    widgetFilesList.removeAll(signedFiles);
+    if (widgetFilesList.isEmpty()) {
+      isAllSigned = true;
+    }
+
+    return isAllSigned;
+  }
+
+  /**
+   * List the files inside the widget folder
+   * 
+   * @param absolutePath
+   * @param role
+   * @return
+   */
+  private HashSet<String> listFilesForFolder(File absolutePath, String role) {
+    File[] list = absolutePath.listFiles();
+
+    for (final File fileEntry : list) {
+      String name = fileEntry.getName();
+      if (!name.startsWith(".")) {
+        if (fileEntry.isDirectory()) {
+          listFilesForFolder(fileEntry, role);
+        }
+
+        else {
+          if (role.equals("author")
+              && ((name.contains("signature")) && (name.endsWith(".xml")))) {
+
+          } else if (!role.equals("author") && name.contains("signature")
+              && !name.contains("author") && (name.endsWith(".xml"))) {
+
+          } else {
+            filesList.add(name);
+          }
+        }
+      }
+    }
+    return filesList;
+  }
+
+  /**
+   * Check whether the certificate sent with the signature is trusted by the
+   * Wookie server
+   * 
+   * @param cert
+   *          : The X.509 certificate sent with the signature
+   * @return : trusted
+   * @throws KeyStoreException
+   * @throws IOException
+   * @throws NoSuchAlgorithmException
+   * @throws CertificateException
+   */
+  private boolean isTrusted(X509Certificate cert) throws KeyStoreException {
+
+    String alias = keystore.getCertificateAlias(cert);
+    if (!(alias == null)) {
+      _logger.debug("Could locate certificate in trusted keystore.");
+      return true;
+
+    }
+    _logger.debug("Couldn't locate certificate in trusted keystore.");
+    return false;
+  }
+
+}

Added: 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/xmldsig-core-schema.xsd
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/xmldsig-core-schema.xsd?rev=1373012&view=auto
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/xmldsig-core-schema.xsd
 (added)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/util/digitalsignature/xmldsig-core-schema.xsd
 Tue Aug 14 18:38:09 2012
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE schema
+    PUBLIC "-//W3C//DTD XMLSchema 200102//EN" 
"http://www.w3.org/2001/XMLSchema.dtd";
+    [
+        <!ATTLIST schema
+            xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#";>
+        <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
+        <!ENTITY % p ''>
+        <!ENTITY % s ''>
+        ]>
+
+<!-- Schema for XML Signatures
+    http://www.w3.org/2000/09/xmldsig#
+    $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
+
+    Copyright 2001 The Internet Society and W3C (Massachusetts Institute
+    of Technology, Institut National de Recherche en Informatique et en
+    Automatique, Keio University). All Rights Reserved.
+    http://www.w3.org/Consortium/Legal/
+
+    This document is governed by the W3C Software License [1] as described
+    in the FAQ [2].
+
+    [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+    [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
+-->
+
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema";
+    xmlns:ds="http://www.w3.org/2000/09/xmldsig#";
+    targetNamespace="http://www.w3.org/2000/09/xmldsig#";
+    version="0.1" elementFormDefault="qualified">
+
+  <!-- Basic Types Defined for Signatures -->
+
+  <simpleType name="CryptoBinary">
+    <restriction base="base64Binary">
+    </restriction>
+  </simpleType>
+
+  <!-- Start Signature -->
+
+  <element name="Signature" type="ds:SignatureType"/>
+  <complexType name="SignatureType">
+    <sequence>
+      <element ref="ds:SignedInfo"/>
+      <element ref="ds:SignatureValue"/>
+      <element ref="ds:KeyInfo" minOccurs="0"/>
+      <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <element name="SignatureValue" type="ds:SignatureValueType"/>
+  <complexType name="SignatureValueType">
+    <simpleContent>
+      <extension base="base64Binary">
+        <attribute name="Id" type="ID" use="optional"/>
+      </extension>
+    </simpleContent>
+  </complexType>
+
+  <!-- Start SignedInfo -->
+
+  <element name="SignedInfo" type="ds:SignedInfoType"/>
+  <complexType name="SignedInfoType">
+    <sequence>
+      <element ref="ds:CanonicalizationMethod"/>
+      <element ref="ds:SignatureMethod"/>
+      <element ref="ds:Reference" maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
+  <complexType name="CanonicalizationMethodType" mixed="true">
+    <sequence>
+      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+  <element name="SignatureMethod" type="ds:SignatureMethodType"/>
+  <complexType name="SignatureMethodType" mixed="true">
+    <sequence>
+      <element name="HMACOutputLength" minOccurs="0" 
type="ds:HMACOutputLengthType"/>
+      <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) external namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+  <!-- Start Reference -->
+
+  <element name="Reference" type="ds:ReferenceType"/>
+  <complexType name="ReferenceType">
+    <sequence>
+      <element ref="ds:Transforms" minOccurs="0"/>
+      <element ref="ds:DigestMethod"/>
+      <element ref="ds:DigestValue"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+    <attribute name="URI" type="anyURI" use="optional"/>
+    <attribute name="Type" type="anyURI" use="optional"/>
+  </complexType>
+
+  <element name="Transforms" type="ds:TransformsType"/>
+  <complexType name="TransformsType">
+    <sequence>
+      <element ref="ds:Transform" maxOccurs="unbounded"/>
+    </sequence>
+  </complexType>
+
+  <element name="Transform" type="ds:TransformType"/>
+  <complexType name="TransformType" mixed="true">
+    <choice minOccurs="0" maxOccurs="unbounded">
+      <any namespace="##other" processContents="lax"/>
+      <!-- (1,1) elements from (0,unbounded) namespaces -->
+      <element name="XPath" type="string"/>
+    </choice>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+  <!-- End Reference -->
+
+  <element name="DigestMethod" type="ds:DigestMethodType"/>
+  <complexType name="DigestMethodType" mixed="true">
+    <sequence>
+      <any namespace="##other" processContents="lax" minOccurs="0" 
maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+  <element name="DigestValue" type="ds:DigestValueType"/>
+  <simpleType name="DigestValueType">
+    <restriction base="base64Binary"/>
+  </simpleType>
+
+  <!-- End SignedInfo -->
+
+  <!-- Start KeyInfo -->
+
+  <element name="KeyInfo" type="ds:KeyInfoType"/>
+  <complexType name="KeyInfoType" mixed="true">
+    <choice maxOccurs="unbounded">
+      <element ref="ds:KeyName"/>
+      <element ref="ds:KeyValue"/>
+      <element ref="ds:RetrievalMethod"/>
+      <element ref="ds:X509Data"/>
+      <element ref="ds:PGPData"/>
+      <element ref="ds:SPKIData"/>
+      <element ref="ds:MgmtData"/>
+      <any processContents="lax" namespace="##other"/>
+      <!-- (1,1) elements from (0,unbounded) namespaces -->
+    </choice>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <element name="KeyName" type="string"/>
+  <element name="MgmtData" type="string"/>
+
+  <element name="KeyValue" type="ds:KeyValueType"/>
+  <complexType name="KeyValueType" mixed="true">
+    <choice>
+      <element ref="ds:DSAKeyValue"/>
+      <element ref="ds:RSAKeyValue"/>
+      <any namespace="##other" processContents="lax"/>
+    </choice>
+  </complexType>
+
+  <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
+  <complexType name="RetrievalMethodType">
+    <sequence>
+      <element ref="ds:Transforms" minOccurs="0"/>
+    </sequence>
+    <attribute name="URI" type="anyURI"/>
+    <attribute name="Type" type="anyURI" use="optional"/>
+  </complexType>
+
+  <!-- Start X509Data -->
+
+  <element name="X509Data" type="ds:X509DataType"/>
+  <complexType name="X509DataType">
+    <sequence maxOccurs="unbounded">
+      <choice>
+        <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+        <element name="X509SKI" type="base64Binary"/>
+        <element name="X509SubjectName" type="string"/>
+        <element name="X509Certificate" type="base64Binary"/>
+        <element name="X509CRL" type="base64Binary"/>
+        <any namespace="##other" processContents="lax"/>
+      </choice>
+    </sequence>
+  </complexType>
+
+  <complexType name="X509IssuerSerialType">
+    <sequence>
+      <element name="X509IssuerName" type="string"/>
+      <element name="X509SerialNumber" type="integer"/>
+    </sequence>
+  </complexType>
+
+  <!-- End X509Data -->
+
+  <!-- Begin PGPData -->
+
+  <element name="PGPData" type="ds:PGPDataType"/>
+  <complexType name="PGPDataType">
+    <choice>
+      <sequence>
+        <element name="PGPKeyID" type="base64Binary"/>
+        <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
+        <any namespace="##other" processContents="lax" minOccurs="0"
+            maxOccurs="unbounded"/>
+      </sequence>
+      <sequence>
+        <element name="PGPKeyPacket" type="base64Binary"/>
+        <any namespace="##other" processContents="lax" minOccurs="0"
+            maxOccurs="unbounded"/>
+      </sequence>
+    </choice>
+  </complexType>
+
+  <!-- End PGPData -->
+
+  <!-- Begin SPKIData -->
+
+  <element name="SPKIData" type="ds:SPKIDataType"/>
+  <complexType name="SPKIDataType">
+    <sequence maxOccurs="unbounded">
+      <element name="SPKISexp" type="base64Binary"/>
+      <any namespace="##other" processContents="lax" minOccurs="0"/>
+    </sequence>
+  </complexType>
+
+  <!-- End SPKIData -->
+
+  <!-- End KeyInfo -->
+
+  <!-- Start Object (Manifest, SignatureProperty) -->
+
+  <element name="Object" type="ds:ObjectType"/>
+  <complexType name="ObjectType" mixed="true">
+    <sequence minOccurs="0" maxOccurs="unbounded">
+      <any namespace="##any" processContents="lax"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+    <attribute name="MimeType" type="string" use="optional"/>
+    <!-- add a grep facet -->
+    <attribute name="Encoding" type="anyURI" use="optional"/>
+  </complexType>
+
+  <element name="Manifest" type="ds:ManifestType"/>
+  <complexType name="ManifestType">
+    <sequence>
+      <element ref="ds:Reference" maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
+  <complexType name="SignaturePropertiesType">
+    <sequence>
+      <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
+  <complexType name="SignaturePropertyType" mixed="true">
+    <choice maxOccurs="unbounded">
+      <any namespace="##other" processContents="lax"/>
+      <!-- (1,1) elements from (1,unbounded) namespaces -->
+    </choice>
+    <attribute name="Target" type="anyURI" use="required"/>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <!-- End Object (Manifest, SignatureProperty) -->
+
+  <!-- Start Algorithm Parameters -->
+
+  <simpleType name="HMACOutputLengthType">
+    <restriction base="integer"/>
+  </simpleType>
+
+  <!-- Start KeyValue Element-types -->
+
+  <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+  <complexType name="DSAKeyValueType">
+    <sequence>
+      <sequence minOccurs="0">
+        <element name="P" type="ds:CryptoBinary"/>
+        <element name="Q" type="ds:CryptoBinary"/>
+      </sequence>
+      <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+      <element name="Y" type="ds:CryptoBinary"/>
+      <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+      <sequence minOccurs="0">
+        <element name="Seed" type="ds:CryptoBinary"/>
+        <element name="PgenCounter" type="ds:CryptoBinary"/>
+      </sequence>
+    </sequence>
+  </complexType>
+
+  <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+  <complexType name="RSAKeyValueType">
+    <sequence>
+      <element name="Modulus" type="ds:CryptoBinary"/>
+      <element name="Exponent" type="ds:CryptoBinary"/>
+    </sequence>
+  </complexType>
+
+  <!-- End KeyValue Element-types -->
+
+  <!-- End Signature -->
+
+</schema>

Modified: incubator/wookie/trunk/src/widgetserver.properties
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/widgetserver.properties?rev=1373012&r1=1373011&r2=1373012&view=diff
==============================================================================
--- incubator/wookie/trunk/src/widgetserver.properties (original)
+++ incubator/wookie/trunk/src/widgetserver.properties Tue Aug 14 18:38:09 2012
@@ -71,4 +71,27 @@ widget.enable.validator=false
 # Broadcast imported widget events to specified url
 # The widget identifier is POSTed to the url defined in 
widget.import.broadcast.url
 widget.import.broadcast=false
-widget.import.broadcast.url=
\ No newline at end of file
+widget.import.broadcast.url=
+#######################################################################
+# digital signature settings
+# Set this property to have Wookie check widget digital signatures when
+# deploying a widget
+widget.deployment.verifysignature=true
+#
+# Set this property to determine how Wookie treats widgets with invalid
+# digital signatures.
+#
+# If set to true, Wookie will not deploy any widgets with invalid
+# digital signatures. If set to false, the widget will be imported
+# and a warning logged.
+widget.deployment.rejectinvalidsignatures=false
+#
+# If set to true, Wookie will only deploy Widgets that have valid digital 
signatures
+# AND that each signature uses a trusted certificate located in the trusted 
keystore,
+# disregarding setting the above to false.
+widget.deployment.rejectuntrustedsignatures=false
+#
+# Name of the trusted keystore file
+widget.deployment.trustedkeystore=wookieKeystore.jks
+#Password for the trusted keystore file
+widget.deployment.trustedkeystore.password = wookie


Reply via email to