From 8132e43c4cb2b9a72066cb13c0caf23ea5cae627 Mon Sep 17 00:00:00 2001 From: John Arthorne Date: Wed, 12 Aug 2009 19:40:40 +0000 Subject: Bug 235526 [security] No prompt for installing unsigned content --- .../p2/core/IServiceUICheckUnsigned.java | 24 ++++ .../internal/p2/engine/EngineActivator.java | 24 ++++ .../provisional/p2/engine/CertificateChecker.java | 45 ++++++- .../internal/provisional/p2/engine/Messages.java | 1 + .../provisional/p2/engine/messages.properties | 3 +- .../eclipse/equinox/p2/tests/engine/AllTests.java | 1 + .../p2/tests/engine/CertificateCheckerTest.java | 149 +++++++++++++++++++++ .../eclipse/actions/CheckTrustAction.java | 7 +- .../equinox/internal/p2/ui/ProvUIMessages.java | 3 + .../equinox/internal/p2/ui/messages.properties | 3 + .../p2/ui/ValidationDialogServiceUI.java | 44 +++++- 11 files changed, 294 insertions(+), 10 deletions(-) create mode 100644 bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/IServiceUICheckUnsigned.java create mode 100644 bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/CertificateCheckerTest.java (limited to 'bundles') diff --git a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/IServiceUICheckUnsigned.java b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/IServiceUICheckUnsigned.java new file mode 100644 index 000000000..e5d36761a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/IServiceUICheckUnsigned.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.core; + +/** + * An extension to {@link IServiceUI} for prompting the user about installing unsigned content. + */ +public interface IServiceUICheckUnsigned { + /** + * Prompts the user that they are installing unsigned content. + * @param details Detailed information about the items that have unsigned content. + * @return true if the installation should proceed, and false otherwise. + */ + public boolean promptForUnsignedContent(String[] details); + +} diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/EngineActivator.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/EngineActivator.java index d020c7670..ead37e3b0 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/EngineActivator.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/EngineActivator.java @@ -33,6 +33,30 @@ public class EngineActivator implements BundleActivator, ServiceTrackerCustomize */ public static final String PROFILE_FORMAT_UNCOMPRESSED = "uncompressed"; //$NON-NLS-1$ + /** + * System property specifying how the engine should handle unsigned artifacts. + * If this property is undefined, the default value is assumed to be "prompt". + */ + public static final String PROP_UNSIGNED_POLICY = "eclipse.p2.unsignedPolicy"; //$NON-NLS-1$ + + /** + * System property value specifying that the engine should prompt for confirmation + * when installing unsigned artifacts. + */ + public static final String UNSIGNED_PROMPT = "prompt"; //$NON-NLS-1$ + + /** + * System property value specifying that the engine should fail when an attempt + * is made to install unsigned artifacts. + */ + public static final String UNSIGNED_FAIL = "fail"; //$NON-NLS-1$ + + /** + * System property value specifying that the engine should silently allow unsigned + * artifacts to be installed. + */ + public static final String UNSIGNED_ALLOW = "allow"; //$NON-NLS-1$ + private ServiceRegistration registration; private ServiceTracker tracker; diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/CertificateChecker.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/CertificateChecker.java index 46c5f034a..e21eb6f50 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/CertificateChecker.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/CertificateChecker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 IBM Corporation and others. + * Copyright (c) 2008, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,8 +21,10 @@ import org.eclipse.core.runtime.Status; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.internal.p2.engine.EngineActivator; import org.eclipse.equinox.internal.provisional.p2.core.IServiceUI; +import org.eclipse.equinox.internal.provisional.p2.core.IServiceUICheckUnsigned; import org.eclipse.osgi.service.security.TrustEngine; import org.eclipse.osgi.signedcontent.*; +import org.eclipse.osgi.util.NLS; import org.osgi.util.tracker.ServiceTracker; public class CertificateChecker { @@ -45,17 +47,20 @@ public class CertificateChecker { SignedContent content = null; SignerInfo[] signerInfo = null; ArrayList untrusted = new ArrayList(); + ArrayList unsigned = new ArrayList(); ArrayList untrustedChain = new ArrayList(); IStatus status = Status.OK_STATUS; if (artifacts.size() == 0 || serviceUI == null) return status; - Iterator artifact = artifacts.iterator(); TrustEngine trustEngine = (TrustEngine) trustEngineTracker.getService(); - while (artifact.hasNext()) { + for (Iterator it = artifacts.iterator(); it.hasNext();) { + File artifact = (File) it.next(); try { - content = verifierFactory.getSignedContent((File) artifact.next()); - if (!content.isSigned()) + content = verifierFactory.getSignedContent(artifact); + if (!content.isSigned()) { + unsigned.add(artifact); continue; + } signerInfo = content.getSignerInfos(); } catch (GeneralSecurityException e) { return new Status(IStatus.ERROR, EngineActivator.ID, Messages.CertificateChecker_SignedContentError, e); @@ -77,7 +82,10 @@ public class CertificateChecker { } } } - if (untrusted.size() > 0) { + status = checkUnsigned(serviceUI, unsigned); + if (status.getSeverity() == IStatus.ERROR || status.getSeverity() == IStatus.CANCEL) + return status; + if (!untrusted.isEmpty()) { Certificate[][] certificates; certificates = new Certificate[untrustedChain.size()][]; for (int i = 0; i < untrustedChain.size(); i++) { @@ -108,6 +116,31 @@ public class CertificateChecker { return status; } + /** + * Perform necessary checks on unsigned content. + */ + private IStatus checkUnsigned(IServiceUI serviceUI, ArrayList unsigned) { + if (unsigned.isEmpty()) + return Status.OK_STATUS; + String policy = EngineActivator.getContext().getProperty(EngineActivator.PROP_UNSIGNED_POLICY); + //if the policy says we should always allow it, there is nothing more to do + if (EngineActivator.UNSIGNED_ALLOW.equals(policy)) + return Status.OK_STATUS; + //if the policy says we should never allow unsigned, then fail + if (EngineActivator.UNSIGNED_FAIL.equals(policy)) + return new Status(IStatus.ERROR, EngineActivator.ID, NLS.bind(Messages.CertificateChecker_UnsignedNotAllowed, unsigned)); + //default policy is to prompt for confirmation if possible + if (serviceUI instanceof IServiceUICheckUnsigned) { + String[] details = new String[unsigned.size()]; + for (int i = 0; i < details.length; i++) { + details[i] = unsigned.get(i).toString(); + } + if (!((IServiceUICheckUnsigned) serviceUI).promptForUnsignedContent(details)) + return Status.CANCEL_STATUS; + } + return Status.OK_STATUS; + } + public void add(File toAdd) { artifacts.add(toAdd); } diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/Messages.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/Messages.java index 2bb088149..b4aef5af8 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/Messages.java +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/Messages.java @@ -20,6 +20,7 @@ public class Messages extends NLS { public static String CertificateChecker_KeystoreConnectionError; public static String CertificateChecker_SignedContentIOError; public static String CertificateChecker_SignedContentError; + public static String CertificateChecker_UnsignedNotAllowed; public static String not_current_phase; public static String null_operands; public static String null_phase; diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/messages.properties b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/messages.properties index e5f18be88..364307adc 100644 --- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/messages.properties +++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/provisional/p2/engine/messages.properties @@ -47,4 +47,5 @@ CertificateChecker_CertificateError=An invalid certificate was found. CertificateChecker_CertificateRejected=One or more certificates rejected. Cannot proceed with installation. CertificateChecker_KeystoreConnectionError=Cannot connect to keystore. CertificateChecker_SignedContentError=Error with signed content. -CertificateChecker_SignedContentIOError=Error reading signed content. \ No newline at end of file +CertificateChecker_SignedContentIOError=Error reading signed content. +CertificateChecker_UnsignedNotAllowed=Installing unsigned artifacts is not permitted: {0} diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/AllTests.java index c3fe46150..de18d1ac1 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/AllTests.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/AllTests.java @@ -19,6 +19,7 @@ public class AllTests extends TestCase { public static Test suite() { TestSuite suite = new TestSuite(AllTests.class.getName()); + suite.addTestSuite(CertificateCheckerTest.class); suite.addTestSuite(DownloadManagerTest.class); suite.addTestSuite(InstructionParserTest.class); suite.addTestSuite(EngineTest.class); diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/CertificateCheckerTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/CertificateCheckerTest.java new file mode 100644 index 000000000..d743d22ee --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/CertificateCheckerTest.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.tests.engine; + +import java.io.File; +import java.io.IOException; +import java.security.cert.Certificate; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.equinox.internal.p2.engine.EngineActivator; +import org.eclipse.equinox.internal.provisional.p2.core.IServiceUI; +import org.eclipse.equinox.internal.provisional.p2.core.IServiceUICheckUnsigned; +import org.eclipse.equinox.internal.provisional.p2.engine.CertificateChecker; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; +import org.eclipse.equinox.p2.tests.TestData; +import org.osgi.framework.ServiceRegistration; + +/** + * Tests for {@link CertificateChecker}. + */ +public class CertificateCheckerTest extends AbstractProvisioningTest { + class CertificateTestService implements IServiceUI, IServiceUICheckUnsigned { + public boolean unsignedReturnValue = true; + public boolean wasPrompted = false; + + public AuthenticationInfo getUsernamePassword(String location) { + return null; + } + + public AuthenticationInfo getUsernamePassword(String location, AuthenticationInfo previousInfo) { + return null; + } + + public boolean promptForUnsignedContent(String[] details) { + wasPrompted = true; + return unsignedReturnValue; + } + + public Certificate[] showCertificates(Certificate[][] certificates) { + return null; + } + + } + + CertificateChecker checker; + ServiceRegistration serviceReg; + CertificateTestService serviceUI; + File unsigned; + + protected void setUp() throws Exception { + checker = new CertificateChecker(); + try { + unsigned = TestData.getFile("CertificateChecker", "unsigned.jar"); + } catch (IOException e) { + fail("0.99", e); + } + assertTrue("1.0", unsigned != null); + assertTrue("1.0", unsigned.exists()); + serviceUI = new CertificateTestService(); + serviceReg = EngineActivator.getContext().registerService(IServiceUI.class.getName(), serviceUI, null); + } + + protected void tearDown() throws Exception { + if (serviceReg != null) + serviceReg.unregister(); + } + + /** + * Tests that installing unsigned content is not allowed when the policy says it must fail. + */ + public void testPolicyAllow() { + try { + //if the service is consulted it will say no + serviceUI.unsignedReturnValue = false; + System.getProperties().setProperty(EngineActivator.PROP_UNSIGNED_POLICY, EngineActivator.UNSIGNED_ALLOW); + checker.add(unsigned); + IStatus result = checker.start(); + assertEquals("1.0", IStatus.OK, result.getSeverity()); + } finally { + System.getProperties().remove(EngineActivator.PROP_UNSIGNED_POLICY); + } + } + + /** + * Tests that installing unsigned content is not allowed when the policy says it must fail. + */ + public void testPolicyFail() { + try { + System.getProperties().setProperty(EngineActivator.PROP_UNSIGNED_POLICY, EngineActivator.UNSIGNED_FAIL); + checker.add(unsigned); + IStatus result = checker.start(); + assertEquals("1.0", IStatus.ERROR, result.getSeverity()); + + } finally { + System.getProperties().remove(EngineActivator.PROP_UNSIGNED_POLICY); + } + } + + /** + * Tests that installing unsigned content with the "prompt" policy and the prompt succeeds. + */ + public void testPolicyPromptSuccess() { + try { + System.getProperties().setProperty(EngineActivator.PROP_UNSIGNED_POLICY, EngineActivator.UNSIGNED_PROMPT); + serviceUI.unsignedReturnValue = true; + checker.add(unsigned); + IStatus result = checker.start(); + assertEquals("1.0", IStatus.OK, result.getSeverity()); + assertTrue("1.1", serviceUI.wasPrompted); + } finally { + System.getProperties().remove(EngineActivator.PROP_UNSIGNED_POLICY); + } + } + + /** + * Tests that the default policy for unsigned content is to prompt. + */ + public void testPolicyDefault() { + System.getProperties().remove(EngineActivator.PROP_UNSIGNED_POLICY); + serviceUI.unsignedReturnValue = true; + checker.add(unsigned); + IStatus result = checker.start(); + assertEquals("1.0", IStatus.OK, result.getSeverity()); + assertTrue("1.1", serviceUI.wasPrompted); + } + + /** + * Tests that installing unsigned content with the "prompt" policy and the prompt says no. + */ + public void testPolicyPromptCancel() { + try { + System.getProperties().setProperty(EngineActivator.PROP_UNSIGNED_POLICY, EngineActivator.UNSIGNED_PROMPT); + serviceUI.unsignedReturnValue = false; + checker.add(unsigned); + IStatus result = checker.start(); + assertEquals("1.0", IStatus.CANCEL, result.getSeverity()); + assertTrue("1.1", serviceUI.wasPrompted); + } finally { + System.getProperties().remove(EngineActivator.PROP_UNSIGNED_POLICY); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/CheckTrustAction.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/CheckTrustAction.java index 6b97b9e9a..14baeae6c 100644 --- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/CheckTrustAction.java +++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/actions/CheckTrustAction.java @@ -21,6 +21,8 @@ import org.eclipse.equinox.internal.provisional.p2.engine.IProfile; import org.eclipse.equinox.internal.provisional.p2.engine.ProvisioningAction; import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery; +import org.eclipse.equinox.internal.provisional.p2.query.Collector; /** * This action collects the set of bundle files on which the signature trust check @@ -37,8 +39,11 @@ public class CheckTrustAction extends ProvisioningAction { IInstallableUnit iu = (IInstallableUnit) parameters.get(EclipseTouchpoint.PARM_IU); if (iu == null) return null; - Collection bundleFiles = (Collection) parameters.get(ActionConstants.PARM_ARTIFACT_FILES); IProfile profile = (IProfile) parameters.get(ActionConstants.PARM_PROFILE); + //if the IU is already in the profile there is nothing to do + if (!profile.available(new InstallableUnitQuery(iu.getId(), iu.getVersion()), new Collector(), null).isEmpty()) + return null; + Collection bundleFiles = (Collection) parameters.get(ActionConstants.PARM_ARTIFACT_FILES); IArtifactKey[] artifacts = iu.getArtifacts(); if (artifacts == null) return null; diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java index 5568fe20f..fc929cb4d 100644 --- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java @@ -268,6 +268,9 @@ public class ProvUIMessages extends NLS { public static String ServiceUI_LoginDetails; public static String ServiceUI_LoginRequired; public static String ServiceUI_OK; + public static String ServiceUI_unsigned_message; + public static String ServiceUI_unsigned_title; + public static String ServiceUI_warning_title; public static String UpdateOrInstallWizardPage_Size; public static String Updates_Label; public static String UpdateWizardPage_Description; diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties index 0788a2940..867d8422d 100644 --- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties @@ -45,6 +45,9 @@ ServiceUI_Cancel=Cancel ServiceUI_LoginDetails=Please provide login details for {0} ServiceUI_LoginRequired=Login required ServiceUI_OK=OK +ServiceUI_unsigned_message=Warning: You are installing software that contains unsigned content. The authenticity or validity of this software cannot be established. Do you want to continue with the installation? +ServiceUI_unsigned_title=Installing unsigned content +ServiceUI_warning_title=Security Warning UpdateIUOperationLabel=Update UpdateIUCommandLabel=Up&date... UpdateIUCommandTooltip=See if updates are available for the selected items diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/ValidationDialogServiceUI.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/ValidationDialogServiceUI.java index 6eb6eb946..78078b24f 100644 --- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/ValidationDialogServiceUI.java +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/ValidationDialogServiceUI.java @@ -11,7 +11,7 @@ package org.eclipse.equinox.internal.provisional.p2.ui; import java.security.cert.Certificate; -import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.equinox.internal.p2.ui.ProvUIActivator; import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; @@ -19,16 +19,36 @@ import org.eclipse.equinox.internal.p2.ui.dialogs.TrustCertificateDialog; import org.eclipse.equinox.internal.p2.ui.dialogs.UserValidationDialog; import org.eclipse.equinox.internal.p2.ui.viewers.CertificateLabelProvider; import org.eclipse.equinox.internal.provisional.p2.core.IServiceUI; +import org.eclipse.equinox.internal.provisional.p2.core.IServiceUICheckUnsigned; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.*; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; /** * The default GUI-based implementation of {@link IServiceUI}. */ -public class ValidationDialogServiceUI implements IServiceUI { +public class ValidationDialogServiceUI implements IServiceUI, IServiceUICheckUnsigned { + /** + * Subclassed to add a cancel button to the error dialog. + */ + static class OkCancelErrorDialog extends ErrorDialog { + + public OkCancelErrorDialog(Shell parentShell, String dialogTitle, String message, IStatus status, int displayMask) { + super(parentShell, dialogTitle, message, status, displayMask); + } + + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Details buttons + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true); + createDetailsButton(parent); + } + } public static final QualifiedName SUPPRESS_AUTHENTICATION_JOB_MARKER = new QualifiedName(ProvUIActivator.PLUGIN_ID, "SUPPRESS_AUTHENTICATION_REQUESTS"); //$NON-NLS-1$ @@ -128,4 +148,24 @@ public class ValidationDialogServiceUI implements IServiceUI { } return result[0]; } + + public boolean promptForUnsignedContent(final String[] details) { + final boolean[] result = new boolean[] {false}; + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + public void run() { + Shell shell = ProvUI.getDefaultParentShell(); + OkCancelErrorDialog dialog = new OkCancelErrorDialog(shell, ProvUIMessages.ServiceUI_warning_title, null, createStatus(), IStatus.WARNING); + result[0] = dialog.open() == IDialogConstants.OK_ID; + } + + private IStatus createStatus() { + MultiStatus parent = new MultiStatus(ProvUIActivator.PLUGIN_ID, 0, ProvUIMessages.ServiceUI_unsigned_message, null); + for (int i = 0; i < details.length; i++) { + parent.add(new Status(IStatus.WARNING, ProvUIActivator.PLUGIN_ID, details[i])); + } + return parent; + } + }); + return result[0]; + } } -- cgit v1.2.3