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