Mercurial > hg > release > icedtea-web-1.8
changeset 1276:e09b5c8bf3cb
PolicyEditor updated to use sun.security.provider.PolicyParser
* NEWS: mention new PolicyEditor support for SignedBy and Principals
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java: UI
updates to support SignedBy and Principals
* netx/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewer.java:
likewise
* netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java:
use diamond operator where applicable
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorController.java:
refactor to support use of PolicyIdentifiers rather than plain codebases
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java:
replace fromString with fromPermissionEntry, fix formatting
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEntry.java:
implement Serializable and Transferable to enable clipboard support. Use
Builder pattern. Support PolicyIdentifiers rather than only plain codebases
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyFileModel.java:
refactor to support PolicyIdentifiers and use PolicyParser
* netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java:
use PolicyIdentifier to identify current applet by its codebase alone
* netx/net/sourceforge/jnlp/util/docprovider/PolicyEditorTextsProvider.java:
remove -codebase from PolicyEditor help text
* netx/net/sourceforge/jnlp/OptionsDefinitions.java: add SIGNEDBY and
PRINCIPALS for PolicyEditor, define CODEBASE to take exactly one argument
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewerTest.java:
use PolicyIdentifier rather than codebase string
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorControllerTest.java:
redo to use PolicyIdentifiers, DisplayablePermissions
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java:
use PolicyIdentifier rather than codebase string
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissionsTest.java
(testActionsRegex, testTargetRegex,
testRegexesAgainstBadPermissionNames): removed, PolicyParser has replaced
this
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorTest.java:
use PolicyIdentifier rather than codebase string
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEntryTest.java:
use DisplayablePermission and PolicyEntry rather than CustomPermission
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyFileModelTest.java:
use PolicyIdentifier rather than codebase string
* netx/net/sourceforge/jnlp/security/policyeditor/KeystoreInfo.java: new
file
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyIdentifier.java:
new file
* netx/net/sourceforge/jnlp/security/policyeditor/CustomPermission.java:
removed
* netx/net/sourceforge/jnlp/security/policyeditor/InvalidPolicyException.java:
removed
* tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPermissionTest.java:
removed
* netx/net/sourceforge/jnlp/resources/Messages.properties: many changes to
PolicyEditor messages for key bindings, UI messages, error messages, etc.
* netx/net/sourceforge/jnlp/resources/Messages_cs.properties: likewise
* netx/net/sourceforge/jnlp/resources/Messages_de.properties: likewise
* netx/net/sourceforge/jnlp/resources/Messages_pl.properties: likewise
line wrap: on
line diff
--- a/ChangeLog Wed Jul 29 18:08:16 2015 +0200 +++ b/ChangeLog Thu Jul 30 10:57:21 2015 -0400 @@ -63,6 +63,63 @@ * tests/reproducers/custom/UnsignedContentInMETAINF/srcs/Makefile: same +2015-07-27 Andrew Azores <aazores@redhat.com> + + PolicyEditor updated to use sun.security.provider.PolicyParser + * NEWS: mention new PolicyEditor support for SignedBy and Principals + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java: UI + updates to support SignedBy and Principals + * netx/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewer.java: + likewise + * netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java: + use diamond operator where applicable + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorController.java: + refactor to support use of PolicyIdentifiers rather than plain codebases + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java: + replace fromString with fromPermissionEntry, fix formatting + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyEntry.java: + implement Serializable and Transferable to enable clipboard support. Use + Builder pattern. Support PolicyIdentifiers rather than only plain codebases + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyFileModel.java: + refactor to support PolicyIdentifiers and use PolicyParser + * netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java: + use PolicyIdentifier to identify current applet by its codebase alone + * netx/net/sourceforge/jnlp/util/docprovider/PolicyEditorTextsProvider.java: + remove -codebase from PolicyEditor help text + * netx/net/sourceforge/jnlp/OptionsDefinitions.java: add SIGNEDBY and + PRINCIPALS for PolicyEditor, define CODEBASE to take exactly one argument + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewerTest.java: + use PolicyIdentifier rather than codebase string + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorControllerTest.java: + redo to use PolicyIdentifiers, DisplayablePermissions + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java: + use PolicyIdentifier rather than codebase string + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissionsTest.java + (testActionsRegex, testTargetRegex, + testRegexesAgainstBadPermissionNames): removed, PolicyParser has replaced + this + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorTest.java: + use PolicyIdentifier rather than codebase string + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEntryTest.java: + use DisplayablePermission and PolicyEntry rather than CustomPermission + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyFileModelTest.java: + use PolicyIdentifier rather than codebase string + * netx/net/sourceforge/jnlp/security/policyeditor/KeystoreInfo.java: new + file + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyIdentifier.java: + new file + * netx/net/sourceforge/jnlp/security/policyeditor/CustomPermission.java: + removed + * netx/net/sourceforge/jnlp/security/policyeditor/InvalidPolicyException.java: + removed + * tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPermissionTest.java: + removed + * netx/net/sourceforge/jnlp/resources/Messages.properties: many changes to + PolicyEditor messages for key bindings, UI messages, error messages, etc. + * netx/net/sourceforge/jnlp/resources/Messages_cs.properties: likewise + * netx/net/sourceforge/jnlp/resources/Messages_de.properties: likewise + * netx/net/sourceforge/jnlp/resources/Messages_pl.properties: likewise + 2015-07-23 Jiri Vanek <jvanek@redhat.com> Enabled and properly tested Entry-Point attribute check
--- a/NEWS Wed Jul 29 18:08:16 2015 +0200 +++ b/NEWS Thu Jul 30 10:57:21 2015 -0400 @@ -30,15 +30,16 @@ - fixed issue with -html receiving garbage in width and height * PolicyEditor - file flag made to work when used standalone + - support for SignedBy and Principals along with existing Codebase New in release 1.6 (2015-XX-XX): * Massively improved offline abilities. Added Xoffline switch to force work without inet connection. * Improved to be able to run with any JDK * JDK 6 and older no longer supported * JDK 8 support added (URLPermission granted if applicable) -* JDK 9 supported +* JDK 9 supported * Added support for Entry-Point manifest attribute -* Added KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK deployment property to control scan of Manifest file +* Added KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK deployment property to control scan of Manifest file * starting arguments now accept also -- abbreviations * Added new documentation * Added support for menu shortcuts - both javaws applications/applets and html applets are supported @@ -202,7 +203,7 @@ New in release 1.1 (2011-XX-XX): * Security updates - - S6983554, CVE-2010-4450: Launcher incorrect processing of empty library path entries + - S6983554, CVE-2010-4450: Launcher incorrect processing of empty library path entries - RH677332, CVE-2011-0706: IcedTea multiple signers privilege escalation * New Features - IcedTea-Web now installs to a FHS-compliant location
--- a/netx/net/sourceforge/jnlp/OptionsDefinitions.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/OptionsDefinitions.java Thu Jul 30 10:57:21 2015 -0400 @@ -86,7 +86,9 @@ //policyeditor //-help FILE("-file", "policy_file", "PBOFile", NumberOfArguments.ONE), - CODEBASE("-codebase", "url", "PBOCodebase", NumberOfArguments.ONE_OR_MORE); + CODEBASE("-codebase", "url", "PBOCodebase", NumberOfArguments.ONE), + SIGNEDBY("-signedby", "certificate_alias", "PBOSignedBy", NumberOfArguments.ONE), + PRINCIPALS("-principals", "class_name principal_name", "PBOPrincipals", NumberOfArguments.EVEN_NUMBER_SUPPORTS_EQUALS_CHAR); public final String option; @@ -175,6 +177,8 @@ OPTIONS.HELP1, OPTIONS.FILE, OPTIONS.CODEBASE, + OPTIONS.SIGNEDBY, + OPTIONS.PRINCIPALS, OPTIONS.VERBOSE } );
--- a/netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java Thu Jul 30 10:57:21 2015 -0400 @@ -166,6 +166,7 @@ private void launchSimplePolicyEditor(final String filePath) { if (policyEditor == null || policyEditor.getPolicyEditor().isClosed()) { policyEditor = PolicyEditor.getPolicyEditorFrame(filePath); + policyEditor.getPolicyEditor().openAndParsePolicyFile(); policyEditor.asWindow().setVisible(true); } else { policyEditor.asWindow().toFront();
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties Thu Jul 30 10:57:21 2015 -0400 @@ -356,10 +356,13 @@ IBOCheck=Checks that all the current settings have valid values. PBOFile=Specifies a policy file path to open. If exactly one argument is given, and it is not this flag, it is interpreted as a file path to open, as if this flag was given first. This flag exists \ -mostly for compatibility with Policy Tool, but is also needed when opening a policy file and also using the -codebase flag. -PBOCodebase=Specifies an applet codebase URL. If the specified codebase already exists in the policy file (if any), then it will be selected when the editor opens. If it is a new codebase then it will \ -be added and selected. Multiple URLs may also be given with a single -codebase flag by separating them with spaces. In this case, the last codebase given will be selected, and all will be \ -added. If this flag is given more than once, only the first is used. +mostly for compatibility with Policy Tool. +PBOCodebase=Specifies an applet codebase URL. This can be used with the other selector options to select a policy entry upon opening the editor; \ +if no such identifier exists then it will be created and then selected. +PBOSignedBy=Specifies a certificate alias for a certificate stored in the keystore. This can be used with the other selector options to select a policy entry upon opening the editor; \ +if no such identifier exists then it will be created and then selected. +PBOPrincipals=Specifies class name/principal name pairs (space-separated) for the policy entry identifier. This can be used with the other selector options to select a policy entry upon opening the editor; \ +if no such identifier exists then it will be created and then selected. # Option Parser OPUnevenParams=For option {0} expected an even number of params. @@ -722,14 +725,17 @@ PEGetEnvDetail=Allow applets to read system environment variables PECouldNotOpen=Unable to open policy file PECouldNotSave=Unable to save policy file -PEAddCodebase=Add new Codebase -PERemoveCodebase=Remove -PECodebasePrompt=Enter a new codebase +PEAddEntry=Add New... +PERemoveEntry=Remove +PEEntryPrompt=Enter a new policy entry identifier +PEAddPrincipal=Add Principal +PERemovePrincipal=Remove Principal +PEEditPrincipal=Edit Principal PEGlobalSettings=All Applets PESaveChanges=Save changes before exiting? PEChangesSaved=Changes saved PECheckboxLabel=Permissions -PECodebaseLabel=Codebases +PEEntriesLabel=Entries PEFileMenu=File PENewMenuItem=New PEOpenMenuItem=Open... @@ -737,26 +743,38 @@ PESaveMenuItem=Save PESaveAsMenuItem=Save As... PEExitMenuItem=Exit -PECodebaseMenu=Codebase -PEAddCodebaseItem=Add New... -PERemoveCodebaseItem=Remove -PERenameCodebaseItem=Rename -PECopyCodebaseItem=Copy -PEPasteCodebaseItem=Paste... -PERenameCodebase=Rename codebase to: -PEPasteCodebase=Paste copied codebase as: +PEEntryMenu=Entry +PEAddEntryItem=Add New... +PERemoveEntryItem=Remove +PEModifySubmenuItem=Modify +PEModifyCodebaseItem=Codebase +PEModifySignedByItem=Signed By +PEModifyPrincipalsItem=Principals +PECopyEntryItem=Copy +PEPasteEntryItem=Paste... +PEModifyCodebase=Change Codebase to: +PEModifyPrincipals=Modify Principals: +PEModifySignedBy=Changed SignedBy to: +PEPasteEntry=Paste copied entry with codebase: PEViewMenu=View PECustomPermissionsItem=Custom Permissions... +PECodebaseInputLabel=Codebase URL: +PESignedByInputLabel=SignedBy: +PEPrincipalsInputLabel=Principals: +PEPrincipalClassNameInputLabel=Class Name: +PEPrincipalPrincipalNameInputLabel=Principal Name: PEFileModified=File Modification Warning PEFileModifiedDetail=The policy file at {0} has been modified since it was opened. Reload and re-edit before saving? PEFileMissing=The policy file was missing from disk. A new file has been saved with the same name. -PEGAccesUnowenedCode = Execute unowned code -PEGMediaAccess = Media access -PEGrightClick = right click to fold/unfold -PEGReadFileSystem = Read from system -PEGWriteFileSystem = Write to system +PEGAccessUnownedCode=Execute unowned code +PEGMediaAccess=Media access +PEGRightClick=Right click to fold/unfold +PEGReadFileSystem=Read from system +PEGWriteFileSystem=Write to system PEClipboardError=Clipboard does not appear to contain properly formatted policy entries -PEInvalidPolicy=Paste Failed: Could not read policy entry for codebase {0} from system clipboard +PEInvalidPolicy=Paste Failed: Could not read policy entry for entry {0} from system clipboard +PEInvalidIdentifier=Please fill in/modify at least one of the fields. +PEIdentifierMatchesAll=Please fill in/modify at least one of the fields. PEClipboardAccessError=Could not read from clipboard PEHelpMenu=Help @@ -799,31 +817,33 @@ # PolicyEditor key mnemonics. See KeyEvent.VK_* PEFileMenuMnemonic=F -PECodebaseMenuMnemonic=C +PEEntryMenuMnemonic=E PEViewMenuMnemonic=V PEHelpMenuMnemonic=H -PEAddCodebaseMnemonic=N -PEAddCodebaseItemMnemonic=N -PERemoveCodebaseMnemonic=R -PERemoveCodebaseItemMnemonic=R +PEAddEntryMnemonic=N +PEAddEntryItemMnemonic=N +PERemoveEntryMnemonic=R +PERemoveEntryItemMnemonic=R PENewMenuItemMnemonic=N PEOpenMenuItemMnemonic=O PEOpenDefaultMenuItemMnemonic=D PESaveMenuItemMnemonic=S PEExitMenuItemMnemonic=X PECustomPermissionsItemMnemonic=U -PECopyCodebaseItemMnemonic=C -PEPasteCodebaseItemMnemonic=P -PECopyCodebaseToClipboardItemMnemonic=U +PECopyEntryItemMnemonic=C +PEPasteEntryItemMnemonic=P PESaveAsMenuItemMnemonic=A -PERenameCodebaseItemMnemonic=E +PEModifySubmenuItemMnemonic=M +PEModifyEntryCodebaseItemMnemonic=B +PEModifyEntryPrincipalsItemMnemonic=I +PEModifyEntrySignedByItemMnemonic=G PEAboutPolicyEditorItemMnemonic=A PEPolicyEditorHelpItemMnemonic=H # See javax.swing.KeyStroke.getKeyStroke(String) -PEAddCodebaseItemAccelerator=control shift N -PERemoveCodebaseItemAccelerator=DELETE +PEAddEntryItemAccelerator=control shift N +PERemoveEntryItemAccelerator=DELETE PENewMenuItemAccelerator=control N PEOpenMenuItemAccelerator=control O PEOpenDefaultMenuItemAccelerator=control D @@ -831,10 +851,11 @@ PESaveAsMenuItemAccelerator=control shift S PEExitMenuItemAccelerator=control Q PECustomPermissionsItemAccelerator=control U -PECopyCodebaseItemAccelerator=control C -PEPasteCodebaseItemAccelerator=control V -PERenameCodebaseItemAccelerator=F2 -PECopyCodebaseToClipboardItemAccelerator=control shift C +PECopyEntryItemAccelerator=control C +PEPasteEntryItemAccelerator=control V +PEModifyEntryCodebaseItemAccelerator=F2 +PEModifyEntryPrincipalsItemAccelerator=shift F2 +PEModifyEntrySignedByItemAccelerator=control F2 PEAboutPolicyEditorCloseAccelerator=control Q #conole itself labels
--- a/netx/net/sourceforge/jnlp/resources/Messages_cs.properties Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/resources/Messages_cs.properties Thu Jul 30 10:57:21 2015 -0400 @@ -675,14 +675,14 @@ PEGetEnvDetail=Umo\u017en\u00ed aplet\u016fm p\u0159\u00edstup ke \u010dten\u00ed prom\u011bnn\u00fdch syst\u00e9mov\u00e9ho prost\u0159ed\u00ed. PECouldNotOpen=Nelze otev\u0159\u00edt soubor se z\u00e1sadami PECouldNotSave=Nelze ulo\u017eit soubor se z\u00e1sadami -PEAddCodebase=P\u0159idat novou z\u00e1kladnu k\u00f3du (codebase) -PERemoveCodebase=Odstranit -PECodebasePrompt=Zadejte novou z\u00e1kladnu k\u00f3du (codebase) +PEAddEntry=P\u0159idat novou z\u00e1kladnu k\u00f3du (codebase) +PERemoveEntry=Odstranit +PEEntryPrompt=Zadejte novou z\u00e1kladnu k\u00f3du (codebase) PEGlobalSettings=V\u0161echny aplety PESaveChanges=Ulo\u017eit zm\u011bny p\u0159ed ukon\u010den\u00edm? PEChangesSaved=Zm\u011bny byly ulo\u017eeny. PECheckboxLabel=Opr\u00e1vn\u011bn\u00ed -PECodebaseLabel=Z\u00e1kladny k\u00f3du (codebases) +PEEntriesLabel=Z\u00e1kladny k\u00f3du (codebases) PEFileMenu=Soubor PENewMenuItem=Nov\u00fd PEOpenMenuItem=Otev\u0159\u00edt... @@ -690,22 +690,22 @@ PESaveMenuItem=Ulo\u017eit PESaveAsMenuItem=Ulo\u017eit jako... PEExitMenuItem=Ukon\u010dit -PECodebaseMenu=Z\u00e1kladna k\u00f3du (codebase) -PEAddCodebaseItem=P\u0159idat novou... -PERemoveCodebaseItem=Odstranit -PERenameCodebaseItem=P\u0159ejmenovat -PECopyCodebaseItem=Kop\u00edrovat -PEPasteCodebaseItem=Vlo\u017eit... -PERenameCodebase=P\u0159ejmenovat z\u00e1kladnu k\u00f3du (codebase) na: -PEPasteCodebase=Vlo\u017eit kop\u00edrovanou z\u00e1kladnu k\u00f3du (codebase) jako: +PEEntryMenu=Z\u00e1kladna k\u00f3du (codebase) +PEAddEntryItem=P\u0159idat novou... +PERemoveEntryItem=Odstranit +PEModifyCodebaseItem=P\u0159ejmenovat +PECopyEntryItem=Kop\u00edrovat +PEPasteEntryItem=Vlo\u017eit... +PEModifyCodebase=P\u0159ejmenovat z\u00e1kladnu k\u00f3du (codebase) na: +PEPasteEntry=Vlo\u017eit kop\u00edrovanou z\u00e1kladnu k\u00f3du (codebase) jako: PEViewMenu=Zobrazit PECustomPermissionsItem=Vlastn\u00ed opr\u00e1vn\u011bn\u00ed PEFileModified=Varov\u00e1n\u00ed ohledn\u011b zm\u011bny souboru PEFileModifiedDetail=Soubor se z\u00e1sadami v um\u00edst\u011bn\u00ed {0} byl od posledn\u00edho otev\u0159en\u00ed zm\u011bn\u011bn. Chcete ho p\u0159ed ulo\u017een\u00edm znovu na\u010d\u00edst a upravit? PEFileMissing=Soubor se z\u00e1sadami na disku chyb\u011bl. Byl ulo\u017een nov\u00fd soubor se stejn\u00fdm n\u00e1zvem. -PEGAccesUnowenedCode= Spou\u0161t\u011bn\u00ed k\u00f3du, kter\u00fd nevlastn\u00edte +PEGAccessUnownedCode= Spou\u0161t\u011bn\u00ed k\u00f3du, kter\u00fd nevlastn\u00edte PEGMediaAccess= P\u0159\u00edstup k m\u00e9di\u00edm -PEGrightClick= Prav\u00fdm tla\u010d\u00edtkem my\u0161i rozbalit/sbalit nab\u00eddku +PEGRightClick= Prav\u00fdm tla\u010d\u00edtkem my\u0161i rozbalit/sbalit nab\u00eddku PEGReadFileSystem= \u010cten\u00ed ze syst\u00e9mu PEGWriteFileSystem= Zapisov\u00e1n\u00ed do syst\u00e9mu PEClipboardError=Zd\u00e1 se, \u017ee schr\u00e1nka neobsahuje pat\u0159i\u010dn\u011b form\u00e1tovan\u00e9 polo\u017eky z\u00e1sad. @@ -731,31 +731,31 @@ # PolicyEditor key mnemonics. See KeyEvent.VK_* PEFileMenuMnemonic=F -PECodebaseMenuMnemonic=C +PEEntryMenuMnemonic=C PEViewMenuMnemonic=V PEHelpMenuMnemonic=H -PEAddCodebaseMnemonic=N -PEAddCodebaseItemMnemonic=N -PERemoveCodebaseMnemonic=R -PERemoveCodebaseItemMnemonic=R +PEAddEntryMnemonic=N +PEAddEntryItemMnemonic=N +PERemoveEntryMnemonic=R +PERemoveEntryItemMnemonic=R PENewMenuItemMnemonic=N PEOpenMenuItemMnemonic=O PEOpenDefaultMenuItemMnemonic=D PESaveMenuItemMnemonic=S PEExitMenuItemMnemonic=X PECustomPermissionsItemMnemonic=U -PECopyCodebaseItemMnemonic=C -PEPasteCodebaseItemMnemonic=P +PECopyEntryItemMnemonic=C +PEPasteEntryItemMnemonic=P PECopyCodebaseToClipboardItemMnemonic=U PESaveAsMenuItemMnemonic=A -PERenameCodebaseItemMnemonic=E +PEModifyEntryCodebaseItemMnemonic=E PEAboutPolicyEditorItemMnemonic=A PEPolicyEditorHelpItemMnemonic=H # See javax.swing.KeyStroke.getKeyStroke(String) -PEAddCodebaseItemAccelerator=ctrl shift N -PERemoveCodebaseItemAccelerator=DEL +PEAddEntryItemAccelerator=ctrl shift N +PERemoveEntryItemAccelerator=DEL PENewMenuItemAccelerator=ctrl N PEOpenMenuItemAccelerator=ctrl O PEOpenDefaultMenuItemAccelerator=ctrl D @@ -763,9 +763,9 @@ PESaveAsMenuItemAccelerator=ctrl shift S PEExitMenuItemAccelerator=ctrl Q PECustomPermissionsItemAccelerator=ctrl U -PECopyCodebaseItemAccelerator=ctrl C -PEPasteCodebaseItemAccelerator=ctrl V -PERenameCodebaseItemAccelerator=F2 +PECopyEntryItemAccelerator=ctrl C +PEPasteEntryItemAccelerator=ctrl V +PEModifyEntryCodebaseItemAccelerator=F2 PECopyCodebaseToClipboardItemAccelerator=ctrl shift C PEAboutPolicyEditorCloseAccelerator=ctrl Q
--- a/netx/net/sourceforge/jnlp/resources/Messages_de.properties Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/resources/Messages_de.properties Thu Jul 30 10:57:21 2015 -0400 @@ -561,14 +561,14 @@ PEGetEnvDetail=Applets das Lesen von Systemumgebungsvariablen erlauben PECouldNotOpen=Kann die Richtliniendatei nicht \u00f6ffnen PECouldNotSave=Kann die Richtliniendatei nicht speichern -PEAddCodebase=Neue Codebasis hinzuf\u00fcgen -PERemoveCodebase=Entfernen -PECodebasePrompt=Eine neue Codebasis eingeben: +PEAddEntry=Neue Codebasis hinzuf\u00fcgen +PERemoveEntry=Entfernen +PEEntryPrompt=Eine neue Codebasis eingeben: PEGlobalSettings=Alle Applets PESaveChanges=Sollen die \u00c4nderungen vor dem Beenden gespeichert werden? PEChangesSaved=\u00c4nderungen gespeichert PECheckboxLabel=Berechtigungen -PECodebaseLabel=Codebasen +PEEntriesLabel=Codebasen PEFileMenu=Datei PEOpenMenuItem=\u00d6ffnen... PESaveMenuItem=Speichern @@ -578,9 +578,9 @@ PECustomPermissionsItem=Benutzerdefinierte Berechtigungen... PEFileModified=Datei\u00e4nderungswarnung PEFileModifiedDetail=Die Richtliniendatei \u201e{0}\u201c wurde ge\u00e4ndert seit sie ge\u00f6ffnet wurde.\nNeu laden und bearbeiten vor dem Speichern? -PEGAccesUnowenedCode=Fremden Code ausf\u00fchren +PEGAccessUnownedCode=Fremden Code ausf\u00fchren PEGMediaAccess=Medienzugriff -PEGrightClick=Rechtsklick zum auf-/zuklappen +PEGRightClick=Rechtsklick zum auf-/zuklappen PEGReadFileSystem=Zum System lesen PEGWriteFileSystem=Zum System schreiben @@ -597,9 +597,9 @@ # PolicyEditor key mnemonics. See java.awt.event.KeyEvent.VK_* # N -PEAddCodebaseMnemonic=78 +PEAddEntryMnemonic=78 # E -PERemoveCodebaseMnemonic=69 +PERemoveEntryMnemonic=69 # O PEOkButtonMnemonic=79 # A
--- a/netx/net/sourceforge/jnlp/resources/Messages_pl.properties Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/resources/Messages_pl.properties Thu Jul 30 10:57:21 2015 -0400 @@ -558,33 +558,33 @@ PEGetEnvDetail=Zezwala aplet-om na odczyt zmiennych \u015brodowiskowych PECouldNotOpen=Nie mo\u017cna otworzy\u0107 pliku wytycznej PECouldNotSave=Nie mo\u017cna zapisa\u0107 pliku wytycznej -PEAddCodebase=Dodaj baz\u0119 kodu -PERemoveCodebase=Usu\u0144 -PECodebasePrompt=Podaj now\u0105 baz\u0119 kodu +PEAddEntry=Dodaj baz\u0119 kodu +PERemoveEntry=Usu\u0144 +PEEntryPrompt=Podaj now\u0105 baz\u0119 kodu PEGlobalSettings=Wszystkie Applet-y PESaveChanges=Zapisa\u0107 zmiany przed zako\u0144czeniem? PEChangesSaved=Zapisano zmiany PECheckboxLabel=Uprawniena -PECodebaseLabel=Bazy kodu +PEEntriesLabel=Bazy kodu PEFileMenu=Plik PEOpenMenuItem=Otw\u00f3rz... PESaveMenuItem=Zapisz PESaveAsMenuItem=Zapisz\u00a0jako... PEExitMenuItem=Zako\u0144cz PEEditMenu=Edycja -PERenameCodebaseItem=Przemianuj baz\u0119 kodu -PECopyCodebaseItem=Kopiuj baz\u0119 kodu -PEPasteCodebaseItem=Wklej baz\u0119 kodu +PEModifyCodebaseItem=Przemianuj baz\u0119 kodu +PECopyEntryItem=Kopiuj baz\u0119 kodu +PEPasteEntryItem=Wklej baz\u0119 kodu PECopyCodebaseToClipboardItem=Kopiuj URL bazy kodu do schowka -PERenameCodebase=Przemianowana baza kodu: -PEPasteCodebase=Skopiowana baza kodu: +PEModifyCodebase=Przemianowana baza kodu: +PEPasteEntry=Skopiowana baza kodu: PEViewMenu=Widok PECustomPermissionsItem=Uprawnienia\u00a0dostosowane... PEFileModified=Ostrze\u017cenie o modyfikacji pliku PEFileModifiedDetail=Plik wytycznej \u201e{0}\u201d zosta\u0142 zmodyfikowany od jego otwarcia. Czy chcesz go za\u0142adowa\u0107 ponownie? -PEGAccesUnowenedCode=Wykonanie obcego kodu +PEGAccessUnownedCode=Wykonanie obcego kodu PEGMediaAccess=Dost\u0119p do medi\u00f3w -PEGrightClick=Kliknij prawym klawiszem myszy, aby ro/zwin\u0105\u0107 +PEGRightClick=Kliknij prawym klawiszem myszy, aby ro/zwin\u0105\u0107 PEGReadFileSystem=Odczyt w system PEGWriteFileSystem=Zapis w system
--- a/netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java Thu Jul 30 10:57:21 2015 -0400 @@ -48,6 +48,7 @@ import java.net.URL; import java.security.Permission; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import javax.swing.AbstractButton; @@ -62,7 +63,9 @@ import net.sourceforge.jnlp.security.policyeditor.PolicyEditor; import net.sourceforge.jnlp.security.policyeditor.PolicyEditor.PolicyEditorWindow; import net.sourceforge.jnlp.security.policyeditor.PolicyEditorPermissions; +import net.sourceforge.jnlp.security.policyeditor.PolicyIdentifier; import net.sourceforge.jnlp.util.logging.OutputController; +import sun.security.provider.PolicyParser; public class TemporaryPermissionsButton extends JButton { @@ -169,12 +172,13 @@ if (policyEditorWindow == null || policyEditorWindow.getPolicyEditor().isClosed()) { policyEditorWindow = PolicyEditor.getPolicyEditorDialog(filepath); + policyEditorWindow.getPolicyEditor().openPolicyFileSynchronously(); } else { policyEditorWindow.asWindow().toFront(); policyEditorWindow.asWindow().repaint(); } policyEditorWindow.setModalityType(ModalityType.DOCUMENT_MODAL); - policyEditorWindow.getPolicyEditor().addNewCodebase(file.getCodeBase().toString()); + policyEditorWindow.getPolicyEditor().addNewEntry(new PolicyIdentifier(null, Collections.<PolicyParser.PrincipalEntry>emptySet(), file.getCodeBase().toString())); policyEditorWindow.asWindow().setVisible(true); menu.setVisible(false); }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/CustomPermission.java Wed Jul 29 18:08:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/*Copyright (C) 2014 Red Hat, Inc. - -This file is part of IcedTea. - -IcedTea is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 2. - -IcedTea is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with IcedTea; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. - */ - -package net.sourceforge.jnlp.security.policyeditor; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * This class models a permission entry in a policy file which is not included - * in the default set of permissions used by the PolicyEditor, ie, permissions - * not defined in the enum PolicyEditorPermissions. - */ -public class CustomPermission implements Comparable<CustomPermission> { - - /* Matches eg 'permission java.io.FilePermission "${user.home}${/}*", "read";' - * eg permissions that have a permission type, target, and actions set. - */ - public static final Pattern ACTIONS_PERMISSION = - Pattern.compile("\\s*permission\\s+([\\w\\.]+)\\s+\"([^\"]+)\",\\s*\"([^\"]*)\";.*"); - - /* Matches eg 'permission java.lang.RuntimePermission "queuePrintJob";' - * eg permissions that have a permission type and target, but no actions. - */ - public static final Pattern TARGET_PERMISSION = - Pattern.compile("\\s*permission\\s+([\\w\\.]+)\\s+\"([^\"]+)\";.*"); - - public final String type, target, actions; - - /** - * Constructor for custom basic permissions (ie those without actions). This is equivalent - * to CustomPermission(type, target, "") - * @param type eg java.io.FilePermission - * @param target eg ${user.home}${/}* - */ - public CustomPermission(final String type, final String target) { - this(type, target, ""); - } - - /** - * Constructor for custom permissions with actions - * @param type eg java.io.FilePermission - * @param target eg ${user.home}${/}* - * @param actions eg read,write - */ - public CustomPermission(final String type, final String target, final String actions) { - this.type = type; - this.target = target; - this.actions = actions; - } - - public CustomPermission(final PermissionType type, final PermissionTarget target) { - this(type, target, PermissionActions.NONE); - } - - public CustomPermission(final PermissionType type, final PermissionTarget target, final PermissionActions actions) { - this(type.type, target.target, actions.rawString()); - } - - /** - * Get a CustomPermission from a policy file permission entry string. This is the full - * entry string, eg `permission java.io.FilePermission "${user.home}${/}* "read";` - * @param string the permission entry string - * @return a CustomPermission representing this string - */ - public static CustomPermission fromString(final String string) { - final String typeStr, targetStr, actionsStr; - - final Matcher actionMatcher = ACTIONS_PERMISSION.matcher(string); - if (actionMatcher.matches()) { - typeStr = actionMatcher.group(1); - targetStr = actionMatcher.group(2); - actionsStr = actionMatcher.group(3); - } else { - final Matcher targetMatcher = TARGET_PERMISSION.matcher(string); - if (!targetMatcher.matches()) { - return null; - } - typeStr = targetMatcher.group(1); - targetStr = targetMatcher.group(2); - actionsStr = ""; - } - - return new CustomPermission(typeStr, targetStr, actionsStr); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("permission "); - sb.append(type); - sb.append(" \""); - sb.append(target); - sb.append("\""); - - if (!this.actions.equals(PermissionActions.NONE.rawString())) { - sb.append(", \""); - sb.append(actions); - sb.append("\""); - } - - sb.append(";"); - - return sb.toString(); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (!(o instanceof CustomPermission)) return false; - - final CustomPermission that = (CustomPermission) o; - - if (!actions.equals(that.actions)) return false; - if (!target.equals(that.target)) return false; - if (!type.equals(that.type)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = type.hashCode(); - result = 31 * result + target.hashCode(); - result = 31 * result + actions.hashCode(); - return result; - } - - @Override - public int compareTo(final CustomPermission o) { - if (this == o) { - return 0; - } - final int typeComparison = this.type.compareTo(o.type); - if (typeComparison != 0) { - return typeComparison; - } - final int targetComparison = this.target.compareTo(o.target); - if (targetComparison != 0) { - return targetComparison; - } - final int actionsComparison = this.actions.compareTo(o.actions); - if (actionsComparison != 0) { - return actionsComparison; - } - return 0; - } -}
--- a/netx/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewer.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewer.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,6 +36,8 @@ package net.sourceforge.jnlp.security.policyeditor; +import sun.security.provider.PolicyParser; + import static net.sourceforge.jnlp.runtime.Translator.R; import java.awt.GridBagConstraints; @@ -67,31 +69,32 @@ */ public class CustomPolicyViewer extends JFrame { - private final Collection<CustomPermission> customPermissions = new TreeSet<>(); + private final Collection<DisplayablePermission> customPermissions = new TreeSet<>(); private final JScrollPane scrollPane = new JScrollPane(); - private final DefaultListModel<CustomPermission> listModel = new DefaultListModel<>(); - private final JList<CustomPermission> list = new JList<>(listModel); + private final DefaultListModel<DisplayablePermission> listModel = new DefaultListModel<>(); + private final JList<DisplayablePermission> list = new JList<>(listModel); private final JButton addButton = new JButton(), removeButton = new JButton(), closeButton = new JButton(); private final JLabel listLabel = new JLabel(); private final ActionListener addButtonAction, removeButtonAction, closeButtonAction; private final PolicyEditor parent; - private final String codebase; + private final PolicyIdentifier policyIdentifier; /** * @param parent the parent PolicyEditor which created this CustomPolicyViewer - * @param codebase the codebase for which these custom permissions are enabled - * @param policyFile the PolicyFileModel + * @param policyIdentifier the policy identifier for which these custom permissions are enabled */ - public CustomPolicyViewer(final PolicyEditor parent, final String codebase) { + public CustomPolicyViewer(final PolicyEditor parent, final PolicyIdentifier policyIdentifier) { super(); Objects.requireNonNull(parent); - Objects.requireNonNull(codebase); + Objects.requireNonNull(policyIdentifier); this.parent = parent; - this.codebase = codebase; + this.policyIdentifier = policyIdentifier; setLayout(new GridBagLayout()); setTitle(R("PECPTitle")); - customPermissions.addAll(parent.getCustomPermissions(codebase)); - for (final CustomPermission perm : customPermissions) { + for (final PolicyParser.PermissionEntry permissionEntry : parent.getCustomPermissions(policyIdentifier)) { + customPermissions.add(DisplayablePermission.from(permissionEntry)); + } + for (final DisplayablePermission perm : customPermissions) { listModel.addElement(perm); } @@ -115,7 +118,7 @@ } else { actions = ""; } - final CustomPermission perm = new CustomPermission(type, target, actions); + final PolicyParser.PermissionEntry perm = new PolicyParser.PermissionEntry(type, target, actions); addCustomPermission(perm); } }; @@ -125,7 +128,7 @@ removeButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - final CustomPermission selected = list.getSelectedValue(); + final PolicyParser.PermissionEntry selected = list.getSelectedValue(); if (selected == null) { return; } @@ -144,13 +147,7 @@ closeButton.setText(R("PECPCloseButton")); closeButton.addActionListener(closeButtonAction); - final String codebaseText; - if (codebase.trim().isEmpty()) { - codebaseText = R("PEGlobalSettings"); - } else { - codebaseText = codebase; - } - listLabel.setText(R("PECPListLabel", codebaseText)); + listLabel.setText(R("PECPListLabel", policyIdentifier.toStringNoHtml())); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); @@ -215,35 +212,83 @@ /** * Update the custom permissions map. Used by the Custom Policy Viewer to update its parent * PolicyEditor to changes it has made - * @param codebase the codebase for which changes were made - * @param permissions the permissions granted to this codebase */ private void updateCustomPermissions() { parent.setChangesMade(true); - parent.clearCustomPermissions(codebase); - for (final CustomPermission permission : customPermissions) { - parent.addCustomPermission(codebase, permission); + parent.clearCustomPermissions(policyIdentifier); + for (final PolicyParser.PermissionEntry permission : customPermissions) { + parent.addCustomPermission(policyIdentifier, permission); } } - void addCustomPermission(final CustomPermission permission) { + void addCustomPermission(final PolicyParser.PermissionEntry permission) { Objects.requireNonNull(permission); - if (customPermissions.add(permission)) { - listModel.addElement(permission); + final DisplayablePermission displayablePermission = DisplayablePermission.from(permission); + if (customPermissions.add(displayablePermission)) { + listModel.addElement(displayablePermission); updateCustomPermissions(); } list.setSelectedValue(permission, true); } - void removeCustomPermission(final CustomPermission permission) { + void removeCustomPermission(final PolicyParser.PermissionEntry permission) { Objects.requireNonNull(permission); - customPermissions.remove(permission); + customPermissions.remove(DisplayablePermission.from(permission)); listModel.removeElement(permission); updateCustomPermissions(); } - Collection<CustomPermission> getCopyOfCustomPermissions() { + Collection<DisplayablePermission> getCopyOfCustomPermissions() { return new TreeSet<>(customPermissions); } + public static class DisplayablePermission extends PolicyParser.PermissionEntry implements Comparable<PolicyParser.PermissionEntry> { + + public DisplayablePermission(final PermissionType type, final PermissionTarget target) { + this(type, target, PermissionActions.NONE); + } + + public DisplayablePermission(final PermissionType type, final PermissionTarget target, final PermissionActions actions) { + this(type.type, target.target, actions.rawString()); + } + + public DisplayablePermission(final String type, final String target) { + this(type, target, null); + } + + public DisplayablePermission(final String permission, final String name, final String action) { + super(permission, name, action); + } + + public static DisplayablePermission from(final PolicyParser.PermissionEntry permissionEntry) { + return new DisplayablePermission(permissionEntry.permission, permissionEntry.name, permissionEntry.action); + } + + @Override + public int compareTo(final PolicyParser.PermissionEntry o) { + return super.name.compareTo(o.name); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("permission "); + sb.append(permission); + sb.append(" \""); + sb.append(name); + sb.append("\""); + + if (this.action == null || !this.action.trim().equals(PermissionActions.NONE.rawString())) { + sb.append(", \""); + sb.append(action); + sb.append("\""); + } + + sb.append(";"); + + return sb.toString(); + } + + } + }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/InvalidPolicyException.java Wed Jul 29 18:08:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/*Copyright (C) 2014 Red Hat, Inc. - -This file is part of IcedTea. - -IcedTea is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 2. - -IcedTea is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with IcedTea; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. - */ - -package net.sourceforge.jnlp.security.policyeditor; - -public class InvalidPolicyException extends Exception { -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/KeystoreInfo.java Thu Jul 30 10:57:21 2015 -0400 @@ -0,0 +1,110 @@ +/*Copyright (C) 2014 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +package net.sourceforge.jnlp.security.policyeditor; + +import java.net.URL; +import java.util.Objects; + +// http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html +public class KeystoreInfo { + + private final String keyStoreUrl; + private final String keyStoreType; + private final String keyStoreProvider; + private final String keyStorePasswordUrl; + + public KeystoreInfo(final String keyStoreUrl, final String keyStoreType, final String keyStoreProvider, final String keyStorePasswordUrl) { + this.keyStoreUrl = keyStoreUrl; + this.keyStoreType = keyStoreType; + this.keyStoreProvider = keyStoreProvider; + this.keyStorePasswordUrl = keyStorePasswordUrl; + } + + public String getKeyStoreUrl() { + return keyStoreUrl; + } + + public String getKeyStoreType() { + return keyStoreType; + } + + public String getKeyStoreProvider() { + return keyStoreProvider; + } + + public String getKeyStorePasswordUrl() { + return keyStorePasswordUrl; + } + + @Override + public String toString() { + return "KeystoreInfo{" + + "keyStoreUrl='" + keyStoreUrl + '\'' + + ", keyStoreType='" + keyStoreType + '\'' + + ", keyStoreProvider='" + keyStoreProvider + '\'' + + ", keyStorePasswordUrl='" + keyStorePasswordUrl + '\'' + + '}'; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final KeystoreInfo that = (KeystoreInfo) o; + + if (!keyStorePasswordUrl.equals(that.keyStorePasswordUrl)) { + return false; + } + if (!keyStoreProvider.equals(that.keyStoreProvider)) { + return false; + } + if (!keyStoreType.equals(that.keyStoreType)) { + return false; + } + if (!keyStoreUrl.equals(that.keyStoreUrl)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return Objects.hash(keyStoreUrl, keyStoreType, keyStoreProvider, keyStorePasswordUrl); + } +}
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java Thu Jul 30 10:57:21 2015 -0400 @@ -84,7 +84,7 @@ } public Collection<String> getActions() { - return new HashSet<String>(this.actions); + return new HashSet<>(this.actions); } private static Set<String> setFromString(final String string) {
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Thu Jul 30 10:57:21 2015 -0400 @@ -59,9 +59,13 @@ import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -72,6 +76,7 @@ import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.ActionMap; +import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.InputMap; import javax.swing.JButton; @@ -87,6 +92,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; @@ -98,11 +104,13 @@ import javax.swing.border.LineBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; + import net.sourceforge.jnlp.about.AboutDialog; import net.sourceforge.jnlp.OptionsDefinitions; import net.sourceforge.jnlp.config.PathsAndFiles; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.runtime.Translator; import net.sourceforge.jnlp.security.policyeditor.PolicyEditorPermissions.Group; import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.FileUtils.OpenFileResult; @@ -111,62 +119,22 @@ import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; import net.sourceforge.jnlp.util.logging.OutputController; import net.sourceforge.jnlp.util.optionparser.OptionParser; +import sun.security.provider.PolicyParser; /** * This class provides a policy editing tool as a simpler alternate to - * the JDK PolicyTool. It is much simpler than PolicyTool - only - * a handful of pre-defined permissions can be enabled or disabled, - * on a per-codebase basis. There are no considerations for Principals, - * who signed the code, or custom permissions. - * - * This editor has a very simple idea of a policy file's contents. If any - * entries are found which it does not recognize, eg 'grant' blocks which - * have more than zero or one simple codeBase attributes, or 'Principal' - * or other attributes assigned to the "grant block", or any other type - * of complication to a "grant block" beyond a single codebase, - * then all of these pieces of data are disregarded. When the editor saves - * its work, all of this unrecognized data will be overwritten. Since - * the editor has no way to display any of these contents anyway, it would - * be potentially dangerous to allow this information to persist in the - * policy file even after it has been edited and saved, as this would mean - * the policy file contents may not be what the user thinks they are. - * - * Comments in policy files are loosely supported, using both block-style - * comment delimiters and double slashes. Block comments may not, however, - * be placed on a line with "functional" text on the same line. To be - * safe, comments should not be adjacent to "functional" text in the file - * unless those lines are intended to be disregarded, ie commented out. - * Comments will *not* be preserved when PolicyEditor next saves to the - * file. + * the JDK PolicyTool. */ public class PolicyEditor extends JPanel { - /** - * Command line switch to print a help message. - */ - public static final String HELP_FLAG = OptionsDefinitions.OPTIONS.HELP1.option; - - /** - * Command line switch to specify the location of the policy file. - * If not given, then the default DeploymentConfiguration path is used. - */ - public static final String FILE_FLAG = OptionsDefinitions.OPTIONS.FILE.option; - - /** - * Command line switch to specify a new codebase entry to be made. - * Can only be used once, presently. - */ - public static final String CODEBASE_FLAG = OptionsDefinitions.OPTIONS.CODEBASE.option; - - - private boolean closed = false; + private boolean closed = false; private final Map<PolicyEditorPermissions, JCheckBox> checkboxMap = new TreeMap<>(); private final List<JCheckBoxWithGroup> groupBoxList = new ArrayList<>(Group.values().length); private final JScrollPane scrollPane = new JScrollPane(); - private final DefaultListModel<String> listModel = new DefaultListModel<>(); - private final JList<String> list = new JList<>(listModel); + private final DefaultListModel<PolicyIdentifier> listModel = new DefaultListModel<>(); + private final JList<PolicyIdentifier> list = new JList<>(listModel); private final JButton okButton = new JButton(), closeButton = new JButton(), - addCodebaseButton = new JButton(), removeCodebaseButton = new JButton(); + addEntryButton = new JButton(), removeEntryButton = new JButton(); private final JFileChooser fileChooser; private CustomPolicyViewer cpViewer = null; /** @@ -178,9 +146,10 @@ private final WeakReference<PolicyEditor> parentPolicyEditor = new WeakReference<>(this); public final PolicyEditorController policyEditorController = new PolicyEditorController(); - private final ActionListener okButtonAction, addCodebaseButtonAction, - removeCodebaseButtonAction, newButtonAction, openButtonAction, openDefaultButtonAction, saveAsButtonAction, viewCustomButtonAction, - renameCodebaseButtonAction, copyCodebaseButtonAction, pasteCodebaseButtonAction, + private final ActionListener okButtonAction, addEntryButtonAction, + removeEntryButtonAction, newButtonAction, openButtonAction, openDefaultButtonAction, saveAsButtonAction, viewCustomButtonAction, + modifyCodebaseButtonAction, modifyPrincipalsButtonAction, modifySignedByButtonAction, + copyEntryButtonAction, pasteEntryButtonAction, policyEditorHelpButtonAction, aboutPolicyEditorButtonAction, aboutItwButtonAction; private final ActionListener closeButtonAction; @@ -222,6 +191,83 @@ } } + private static class PrincipalsPanel extends JPanel { + + private final DefaultListModel<PolicyParser.PrincipalEntry> principals = new DefaultListModel<>(); + + public PrincipalsPanel(final Collection<PolicyParser.PrincipalEntry> entries) { + super(); + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + for (final PolicyParser.PrincipalEntry principalEntry : entries) { + principals.addElement(principalEntry); + } + final JList<PolicyParser.PrincipalEntry> principalsList = new JList<>(principals); + final JScrollPane scrollPane = new JScrollPane(principalsList); + final JButton addButton = new JButton(R("PEAddPrincipal")); + addButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final JTextField className = new JTextField(); + final JTextField principalName = new JTextField(); + final int option = JOptionPane.showConfirmDialog( + null, + new Object[]{R("PEPrincipalClassNameInputLabel"), className, R("PEPrincipalPrincipalNameInputLabel"), principalName}, + R("PEAddPrincipal"), + JOptionPane.OK_CANCEL_OPTION + ); + if (option == JOptionPane.OK_OPTION) { + final PolicyParser.PrincipalEntry entry = new PolicyParser.PrincipalEntry(className.getText(), principalName.getText()); + principals.addElement(entry); + } + } + }); + final JButton removeButton = new JButton(R("PERemovePrincipal")); + removeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + principals.removeElement(principalsList.getSelectedValue()); + } + }); + final JButton editButton = new JButton(R("PEEditPrincipal")); + editButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final PolicyParser.PrincipalEntry entry = principalsList.getSelectedValue(); + if (entry == null) { + return; + } + final JTextField className = new JTextField(); + final JTextField principalName = new JTextField(); + className.setText(entry.getDisplayClass()); + principalName.setText(entry.getDisplayName()); + final int option = JOptionPane.showConfirmDialog( + null, + new Object[]{R("PEPrincipalClassNameInputLabel"), className, R("PEPrincipalPrincipalNameInputLabel"), principalName}, + R("PEEditPrincipal"), + JOptionPane.OK_CANCEL_OPTION + ); + if (option == JOptionPane.OK_OPTION) { + principals.removeElement(entry); + final PolicyParser.PrincipalEntry newEntry = new PolicyParser.PrincipalEntry(className.getText(), principalName.getText()); + principals.addElement(newEntry); + } + } + }); + add(scrollPane); + add(addButton); + add(editButton); + add(removeButton); + } + + public List<PolicyParser.PrincipalEntry> getPrincipals() { + final List<PolicyParser.PrincipalEntry> entries = new ArrayList<>(principals.size()); + for (final PolicyParser.PrincipalEntry entry : Collections.list(principals.elements())) { + entries.add(entry); + } + return entries; + } + } + public PolicyEditor(final String filepath) { super(); setLayout(new GridBagLayout()); @@ -234,39 +280,7 @@ } setFile(filepath); - if (filepath != null) { - try { - policyEditorController.openAndParsePolicyFile(); - } catch (final FileNotFoundException fnfe) { - OutputController.getLogger().log(fnfe); - FileUtils.showCouldNotOpenDialog(PolicyEditor.this, R("PECouldNotOpen")); - } catch (final IOException | InvalidPolicyException e) { - OutputController.getLogger().log(e); - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RCantOpenFile", policyEditorController.getFile().getPath())); - FileUtils.showCouldNotOpenDialog(PolicyEditor.this, R("PECouldNotOpen")); - } - try { - invokeRunnableOrEnqueueAndWait(new Runnable() { - @Override - public void run() { - for (final String codebase : policyEditorController.getCodebases()) { - final String model; - if (codebase.isEmpty()) { - model = R("PEGlobalSettings"); - } else { - model = codebase; - } - if (!listModel.contains(model)) { - listModel.addElement(model); - } - } - addNewCodebase(""); - } - }); - } catch (final InvocationTargetException | InterruptedException e) { - OutputController.getLogger().log(e); - } - } + addDefaultAllAppletsIdentifier(); setChangesMade(false); fileChooser = new JFileChooser(policyEditorController.getFile()); @@ -284,6 +298,7 @@ // May still be null if user cancelled the file chooser if (policyEditorController.getFile() != null) { + setChangesMade(true); savePolicyFile(); } } @@ -291,28 +306,30 @@ okButton.setText(R("ButApply")); okButton.addActionListener(okButtonAction); - addCodebaseButtonAction = new ActionListener() { + addEntryButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - addNewCodebaseInteractive(); + addNewIdentifierInteractive(); } }; - addCodebaseButton.setText(R("PEAddCodebase")); - addCodebaseButton.addActionListener(addCodebaseButtonAction); + addEntryButton.setText(R("PEAddEntry")); + addEntryButton.addActionListener(addEntryButtonAction); - removeCodebaseButtonAction = new ActionListener() { + removeEntryButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - removeCodebase(getSelectedCodebase()); + removeIdentifier(getSelectedPolicyIdentifier()); } }; - removeCodebaseButton.setText(R("PERemoveCodebase")); - removeCodebaseButton.addActionListener(removeCodebaseButtonAction); + removeEntryButton.setText(R("PERemoveEntry")); + removeEntryButton.addActionListener(removeEntryButtonAction); newButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - if (!promptOnSaveChangesMade(false)) return; + if (!promptOnSaveChangesMade(false)) { + return; + } setFile(null); setChangesMade(false); } @@ -321,7 +338,9 @@ openButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - if (!promptOnSaveChangesMade(true)) return; + if (!promptOnSaveChangesMade(true)) { + return; + } final int choice = fileChooser.showOpenDialog(PolicyEditor.this); if (choice == JFileChooser.APPROVE_OPTION) { PolicyEditor.this.setFile(fileChooser.getSelectedFile().getAbsolutePath()); @@ -330,12 +349,20 @@ } }; - openDefaultButtonAction = new ActionListener() { + openDefaultButtonAction = new ActionListener() { @Override - public void actionPerformed(final ActionEvent e) { - if (!promptOnSaveChangesMade(true)) return; - PolicyEditor.this.setFile(PathsAndFiles.JAVA_POLICY.getFullPath()); - openAndParsePolicyFile(); + public void actionPerformed(final ActionEvent event) { + if (!promptOnSaveChangesMade(true)) { + return; + } + try { + PolicyEditor.this.setFile(new File(new URI(PathsAndFiles.JAVA_POLICY.getFullPath())).getAbsolutePath()); + PolicyEditor.this.getFile().createNewFile(); + } catch (final IOException | URISyntaxException e) { + OutputController.getLogger().log(e); + return; + } + openAndParsePolicyFile(); } }; @@ -351,59 +378,77 @@ } }; - renameCodebaseButtonAction = new ActionListener() { + modifyCodebaseButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - final String oldCodebase = getSelectedCodebase(); - if (oldCodebase.isEmpty()) { + if (getSelectedPolicyIdentifier().equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { return; } - String newCodebase = ""; - while (!validateCodebase(newCodebase) || policyEditorController.getCopyOfPermissions().containsKey(newCodebase)) { - newCodebase = JOptionPane.showInputDialog(PolicyEditor.this, R("PERenameCodebase"), oldCodebase); + final String oldCodebase = getSelectedPolicyIdentifier().getCodebase(); + String newCodebase; + do { + newCodebase = JOptionPane.showInputDialog(PolicyEditor.this, R("PEModifyCodebase"), oldCodebase); if (newCodebase == null) { return; } - } - renameCodebase(oldCodebase, newCodebase); - } - }; - - copyCodebaseButtonAction = new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - copyCodebase(getSelectedCodebase()); + } while (!validateCodebase(newCodebase)); + modifyCodebase(getSelectedPolicyIdentifier(), newCodebase); } }; - pasteCodebaseButtonAction = new ActionListener() { + modifyPrincipalsButtonAction = new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + if (getSelectedPolicyIdentifier().equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { + return; + } + final PrincipalsPanel panel = new PrincipalsPanel(getSelectedPolicyIdentifier().getPrincipals()); + final int option = JOptionPane.showConfirmDialog( + null, + new Object[]{ R("PEPrincipalsInputLabel"), panel }, + R("PEEntryPrompt"), + JOptionPane.OK_CANCEL_OPTION + ); + if (option == JOptionPane.OK_OPTION) { + modifyPrincipals(getSelectedPolicyIdentifier(), panel.getPrincipals()); + } + } + }; + + modifySignedByButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - String clipboardCodebase = null; + if (getSelectedPolicyIdentifier().equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { + return; + } + final String newSignedBy = JOptionPane.showInputDialog(PolicyEditor.this, R("PEModifySignedBy"), getSelectedPolicyIdentifier().getSignedBy()); + if (newSignedBy == null) { + return; + } + modifySignedBy(getSelectedPolicyIdentifier(), newSignedBy); + } + }; + + copyEntryButtonAction = new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + copyEntry(getSelectedPolicyIdentifier()); + } + }; + + pasteEntryButtonAction = new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + PolicyIdentifier identifier = null; try { - clipboardCodebase = policyEditorController.getCodebaseFromClipboard(); - final String newCodebase; - if (getCodebases().contains(clipboardCodebase)) { - String cb = ""; - while (!validateCodebase(cb) || policyEditorController.getCopyOfPermissions().containsKey(cb)) { - cb = JOptionPane.showInputDialog(PolicyEditor.this, R("PEPasteCodebase"), "http://"); - if (cb == null) { - return; - } - } - newCodebase = cb; - } else { - newCodebase = clipboardCodebase; - } - if (validateCodebase(newCodebase)) { - pasteCodebase(newCodebase); - } + identifier = PolicyEditorController.getPolicyEntryFromClipboard().getPolicyIdentifier(); + pasteEntry(promptForPolicyIdentifier(identifier)); } catch (final UnsupportedFlavorException ufe) { OutputController.getLogger().log(ufe); showClipboardErrorDialog(); - } catch (final InvalidPolicyException ipe) { - OutputController.getLogger().log(ipe); - showInvalidPolicyExceptionDialog(clipboardCodebase); + } catch (final PolicyParser.ParsingException pe) { + OutputController.getLogger().log(pe); + showInvalidPolicyExceptionDialog(identifier); } catch (final IOException ioe) { OutputController.getLogger().log(ioe); showCouldNotAccessClipboardDialog(); @@ -417,12 +462,12 @@ invokeRunnableOrEnqueueLater(new Runnable() { @Override public void run() { - String codebase = getSelectedCodebase(); - if (codebase == null) { + final PolicyIdentifier policyIdentifier = getSelectedPolicyIdentifier(); + if (policyIdentifier == null) { return; } if (cpViewer == null) { - cpViewer = new CustomPolicyViewer(PolicyEditor.this, codebase); + cpViewer = new CustomPolicyViewer(PolicyEditor.this, policyIdentifier); cpViewer.setVisible(true); } else { cpViewer.toFront(); @@ -444,11 +489,11 @@ @Override public void actionPerformed(final ActionEvent e) { boolean modal = getModality(); - AboutDialog.display(modal, TextsProvider.POLICY_EDITOR,AboutDialog.ShowPage.HELP); + AboutDialog.display(modal, TextsProvider.POLICY_EDITOR, AboutDialog.ShowPage.HELP); } }; - aboutItwButtonAction = new ActionListener() { + aboutItwButtonAction = new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { boolean modal = getModality(); @@ -470,7 +515,11 @@ setupLayout(); } - + + private void addDefaultAllAppletsIdentifier() { + addNewEntry(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); + } + private boolean getModality() { boolean modal = false; Container parent = PolicyEditor.this; @@ -497,7 +546,7 @@ if (policyEditorController.changesMade()) { final int save = JOptionPane.showConfirmDialog(this, R("PESaveChanges")); if (save == JOptionPane.YES_OPTION) { - if (policyEditorController.getFile() == null) { + if (getFile() == null) { final int choice = fileChooser.showSaveDialog(this); if (choice == JFileChooser.APPROVE_OPTION) { this.setFile(fileChooser.getSelectedFile().getAbsolutePath()); @@ -520,14 +569,14 @@ } return true; } - + public void setFile(final String filepath) { if (filepath != null) { policyEditorController.setFile(new File(filepath)); } else { policyEditorController.setFile(null); - resetCodebases(); - addNewCodebase(""); + resetEntries(); + addDefaultAllAppletsIdentifier(); } setParentWindowTitle(getWindowTitleForStatus()); } @@ -569,15 +618,8 @@ return result; } - private String getSelectedCodebase() { - final String codebase = list.getSelectedValue(); - if (codebase == null || codebase.isEmpty()) { - return null; - } - if (codebase.equals(R("PEGlobalSettings"))) { - return ""; - } - return codebase; + private PolicyIdentifier getSelectedPolicyIdentifier() { + return list.getSelectedValue(); } private static void preparePolicyEditorWindow(final PolicyEditorWindow w, final PolicyEditor e) { @@ -602,23 +644,23 @@ }); } - public static interface PolicyEditorWindow { + public interface PolicyEditorWindow { - public void setTitle(String s); + void setTitle(String s); - public void setDefaultCloseOperation(int i); + void setDefaultCloseOperation(int i); - public PolicyEditor getPolicyEditor(); + PolicyEditor getPolicyEditor(); - public void setPolicyEditor(PolicyEditor e); + void setPolicyEditor(PolicyEditor e); - public void setJMenuBar(JMenuBar menu); + void setJMenuBar(JMenuBar menu); - public Window asWindow(); + Window asWindow(); - public void setModalityType(ModalityType modalityType); + void setModalityType(ModalityType modalityType); - public void quit(); + void quit(); } private static class PolicyEditorFrame extends JFrame implements PolicyEditorWindow { @@ -627,7 +669,7 @@ private PolicyEditorFrame(final PolicyEditor editor) { super(); - preparePolicyEditorWindow((PolicyEditorWindow) this, editor); + preparePolicyEditorWindow(this, editor); } @Override @@ -714,7 +756,7 @@ private PolicyEditorDialog(final PolicyEditor editor) { super(); - preparePolicyEditorWindow((PolicyEditorWindow) this, editor); + preparePolicyEditorWindow(this, editor); } @Override @@ -783,36 +825,39 @@ } /** - * Add a new codebase to the editor's model. If the codebase is not a valid URL, - * the codebase is not added. - * @param codebase to be added + * Add a new identifier to the editor's model. + * @param identifier to be added */ - public void addNewCodebase(final String codebase) { - if (!codebase.isEmpty() && !validateCodebase(codebase)) { - OutputController.getLogger().log("Could not add codebase " + codebase); + public void addNewEntry(final PolicyIdentifier identifier) { + if (!validateCodebase(identifier.getCodebase())) { return; } - final String model; - if (codebase.isEmpty()) { - model = R("PEGlobalSettings"); - } else { - model = codebase; - } - policyEditorController.addCodebase(codebase); + policyEditorController.addIdentifier(identifier); invokeRunnableOrEnqueueLater(new Runnable() { @Override public void run() { - if (!listModel.contains(model)) { - listModel.addElement(model); - setChangesMade(true); + for (final PolicyIdentifier identifier : policyEditorController.getIdentifiers()) { + if (!listModel.contains(identifier)) { + listModel.addElement(identifier); + } } - list.setSelectedValue(model, true); - updateCheckboxes(codebase); + list.setSelectedValue(identifier, true); + updateCheckboxes(identifier); } }); } + static PolicyIdentifier identifierFromCodebase(final String codebase) { + if (codebase.isEmpty() || codebase.equals(Translator.R("PEGlobalSettings"))) { + return PolicyIdentifier.ALL_APPLETS_IDENTIFIER; + } + return new PolicyIdentifier(null, Collections.<PolicyParser.PrincipalEntry>emptyList(), codebase); + } + private static boolean validateCodebase(final String codebase) { + if (codebase == null || codebase.isEmpty()) { + return true; + } try { new URL(codebase); } catch (final MalformedURLException mue) { @@ -821,128 +866,180 @@ return true; } - public File getFile() { return policyEditorController.getFile(); } /** - * Display an input dialog, which will disappear when the user enters a valid URL - * or when the user presses cancel. If an invalid URL is entered, the dialog reappears. - * When a valid URL is entered, it is used to create a new codebase entry in the editor's - * policy file model. + * Display an input dialog, which will disappear when the user enters a valid entry + * or when the user presses cancel. */ - public void addNewCodebaseInteractive() { + public void addNewIdentifierInteractive() { invokeRunnableOrEnqueueLater(new Runnable() { @Override public void run() { - String codebase = ""; - while (!validateCodebase(codebase)) { - codebase = JOptionPane.showInputDialog(PolicyEditor.this, R("PECodebasePrompt"), "http://"); - if (codebase == null) { - return; - } + final PolicyIdentifier identifier = promptForPolicyIdentifier(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); + if (identifier == null) { + return; } - addNewCodebase(codebase); + addNewEntry(identifier); } }); } + private PolicyIdentifier promptForPolicyIdentifier(final PolicyIdentifier initialValues) { + PolicyIdentifier identifier = initialValues; + final JTextField codebase = new JTextField(); + final JTextField signedBy = new JTextField(); + final PrincipalsPanel principalsPanel = new PrincipalsPanel(Collections.<PolicyParser.PrincipalEntry>emptySet()); + while (identifier.equals(initialValues) || identifier.equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER) || !validateCodebase(codebase.getText())) { + codebase.setText(identifier.getCodebase()); + signedBy.setText(identifier.getSignedBy()); + final int option = JOptionPane.showConfirmDialog( + PolicyEditor.this, + new Object[]{R("PECodebaseInputLabel"), codebase, R("PEPrincipalsInputLabel"), principalsPanel, R("PESignedByInputLabel"), signedBy}, + R("PEEntryPrompt"), + JOptionPane.OK_CANCEL_OPTION + ); + if (option == JOptionPane.OK_OPTION) { + final String cb = codebase.getText().trim().isEmpty() ? null : codebase.getText().trim(); + final String sb = signedBy.getText().trim().isEmpty() ? null : signedBy.getText().trim(); + identifier = new PolicyIdentifier(sb, principalsPanel.getPrincipals(), cb); + if (identifier.equals(initialValues)) { + JOptionPane.showMessageDialog(null, R("PEInvalidIdentifier")); + } else if (identifier.equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { + JOptionPane.showMessageDialog(null, R("PEIdentifierMatchesAll")); + } + } else { + return null; + } + } + return identifier; + } + /** - * Remove a codebase from the editor's model - * @param codebase to be removed + * Remove an identifier from the editor's model + * @param identifier to be removed */ - public void removeCodebase(final String codebase) { - if (codebase.equals(R("PEGlobalSettings")) || codebase.isEmpty()) { + public void removeIdentifier(final PolicyIdentifier identifier) { + if (identifier.equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { return; } int previousIndex = list.getSelectedIndex() - 1; if (previousIndex < 0) { previousIndex = 0; } - policyEditorController.removeCodebase(codebase); + policyEditorController.removeIdentifier(identifier); final int fIndex = previousIndex; invokeRunnableOrEnqueueLater(new Runnable() { @Override public void run() { - listModel.removeElement(codebase); + listModel.removeElement(identifier); list.setSelectedIndex(fIndex); } }); setChangesMade(true); } - /** - * Rename a codebase, preserving its permissions - * @param oldCodebase the codebase to rename - * @param newCodebase the new name for the codebase - */ - public void renameCodebase(final String oldCodebase, final String newCodebase) { - final Map<PolicyEditorPermissions, Boolean> permissions = getPermissions(oldCodebase); - final Collection<CustomPermission> customPermissions = getCustomPermissions(oldCodebase); + public void modifyCodebase(final PolicyIdentifier identifier, final String newCodebase) { + final PolicyIdentifier newIdentifier = new PolicyIdentifier(identifier.getSignedBy(), identifier.getPrincipals(), newCodebase); + replaceIdentifier(identifier, newIdentifier); + } + + public void modifyPrincipals(final PolicyIdentifier identifier, final List<PolicyParser.PrincipalEntry> principalEntries) { + final PolicyIdentifier newIdentifier = new PolicyIdentifier(identifier.getSignedBy(), principalEntries, identifier.getCodebase()); + replaceIdentifier(identifier, newIdentifier); + } - removeCodebase(oldCodebase); - addNewCodebase(newCodebase); + public void modifySignedBy(final PolicyIdentifier identifier, final String newSignedBy) { + final PolicyIdentifier newIdentifier = new PolicyIdentifier(newSignedBy, identifier.getPrincipals(), identifier.getCodebase()); + replaceIdentifier(identifier, newIdentifier); + } + + private void replaceIdentifier(final PolicyIdentifier oldIdentifier, final PolicyIdentifier newIdentifier) { + if (oldIdentifier.equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER) || newIdentifier.equals(PolicyIdentifier.ALL_APPLETS_IDENTIFIER)) { + return; + } + + final Map<PolicyEditorPermissions, Boolean> permissions = getPermissions(oldIdentifier); + final Collection<PolicyParser.PermissionEntry> customPermissions = getCustomPermissions(oldIdentifier); + + removeIdentifier(oldIdentifier); + addNewEntry(newIdentifier); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : permissions.entrySet()) { - setPermission(newCodebase, entry.getKey(), entry.getValue()); + setPermission(newIdentifier, entry.getKey(), entry.getValue()); } - for (final CustomPermission permission : customPermissions) { - addCustomPermission(newCodebase, permission); + for (final PolicyParser.PermissionEntry permission : customPermissions) { + addCustomPermission(newIdentifier, permission); } - - updateCheckboxes(newCodebase); + updateCheckboxes(newIdentifier); } /** - * Copy a codebase to the system clipboard, preserving its permissions - * @param codebase the codebase to copy + * Copy an entry to the system clipboard + * @param identifier the identifier to copy */ - public void copyCodebase(final String codebase) { - if (!getCodebases().contains(codebase)) { + public void copyEntry(final PolicyIdentifier identifier) { + if (!policyEditorController.getIdentifiers().contains(identifier)) { return; } - policyEditorController.copyCodebaseToClipboard(codebase); + policyEditorController.copyPolicyEntryToClipboard(identifier); } /** - * Paste a codebase entry from the system clipboard with a new codebase name + * Paste a grant entry from the system clipboard with a new identifier */ - public void pasteCodebase(final String newCodebase) throws UnsupportedFlavorException, InvalidPolicyException, IOException { - final Map<PolicyEditorPermissions, Boolean> permissions = policyEditorController.getPermissionsFromClipboard(); - final Set<CustomPermission> customPermissions = policyEditorController.getCustomPermissionsFromClipboard(); - addNewCodebase(newCodebase); - for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : permissions.entrySet()) { - policyEditorController.setPermission(newCodebase, entry.getKey(), entry.getValue()); - } - policyEditorController.addCustomPermissions(newCodebase, customPermissions); + public void pasteEntry(final PolicyIdentifier identifier) throws UnsupportedFlavorException, PolicyParser.ParsingException, IOException { + addNewEntry(identifier); + final PolicyEntry policyEntry = PolicyEditorController.getPolicyEntryFromClipboard(); + final PolicyEntry newEntry = new PolicyEntry.Builder() + .signedBy(identifier.getSignedBy()) + .principals(identifier.getPrincipals()) + .codebase(identifier.getCodebase()) + .permissions(policyEntry.getPermissions()) + .customPermissions(policyEntry.getCustomPermissions()) + .build(); + policyEditorController.addPolicyEntry(newEntry); setChangesMade(true); - updateCheckboxes(newCodebase); - } - - public Set<String> getCodebases() { - return policyEditorController.getCodebases(); + updateCheckboxes(identifier); } - public void setPermission(final String codebase, final PolicyEditorPermissions permission, final boolean state) { - policyEditorController.setPermission(codebase, permission, state); + Set<String> getCodebases() { + final Set<String> codebases = new HashSet<>(); + for (final PolicyIdentifier identifier : policyEditorController.getIdentifiers()) { + if (isCodeBaseIdentifier(identifier)) { + codebases.add(identifier.getCodebase()); + } + } + return codebases; } - public Map<PolicyEditorPermissions, Boolean> getPermissions(final String codebase) { - return policyEditorController.getPermissions(codebase); + static boolean isCodeBaseIdentifier(final PolicyIdentifier identifier) { + return (identifier.getSignedBy() == null || identifier.getSignedBy().isEmpty()) + && (identifier.getPrincipals() == null || identifier.getPrincipals().isEmpty()) + && identifier.getCodebase() != null; } - public void addCustomPermission(final String codebase, final CustomPermission permission) { - policyEditorController.addCustomPermission(codebase, permission); + public void setPermission(final PolicyIdentifier identifier, final PolicyEditorPermissions permission, final boolean state) { + policyEditorController.setPermission(identifier, permission, state); + } + + public Map<PolicyEditorPermissions, Boolean> getPermissions(final PolicyIdentifier identifier) { + return policyEditorController.getPermissions(identifier); } - public Collection<CustomPermission> getCustomPermissions(final String codebase) { - return policyEditorController.getCustomPermissions(codebase); + public void addCustomPermission(final PolicyIdentifier identifier, final PolicyParser.PermissionEntry permission) { + policyEditorController.addCustomPermission(identifier, permission); } - public void clearCustomPermissions(final String codebase) { - policyEditorController.clearCustomCodebase(codebase); + public Collection<PolicyParser.PermissionEntry> getCustomPermissions(final PolicyIdentifier identifier) { + return policyEditorController.getCustomPermissions(identifier); + } + + public void clearCustomPermissions(final PolicyIdentifier identifier) { + policyEditorController.clearCustomIdentifier(identifier); } private void invokeRunnableOrEnqueueLater(final Runnable runnable) { @@ -962,35 +1059,33 @@ } /** - * Update the checkboxes to show the permissions granted to the specified codebase - * @param codebase whose permissions to display + * Update the checkboxes to show the permissions granted to the specified identifier + * @param identifier whose permissions to display */ - private void updateCheckboxes(final String codebase) { + private void updateCheckboxes(final PolicyIdentifier identifier) { try { invokeRunnableOrEnqueueAndWait(new Runnable() { @Override public void run() { - updateCheckboxesImpl(codebase); + updateCheckboxesImpl(identifier); } }); - } catch (InterruptedException ex) { - OutputController.getLogger().log(ex); - } catch (InvocationTargetException ex) { + } catch (final InterruptedException | InvocationTargetException ex) { OutputController.getLogger().log(ex); } } - private void updateCheckboxesImpl(final String codebase) { - if (!getCodebases().contains(codebase)) { + private void updateCheckboxesImpl(final PolicyIdentifier identifier) { + if (!listModel.contains(identifier)) { return; } - final Map<PolicyEditorPermissions, Boolean> map = policyEditorController.getCopyOfPermissions().get(codebase); + final Map<PolicyEditorPermissions, Boolean> map = policyEditorController.getCopyOfPermissions().get(identifier); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { final JCheckBox box = checkboxMap.get(perm); for (final ActionListener l : box.getActionListeners()) { box.removeActionListener(l); } - final boolean state = policyEditorController.getPermission(codebase, perm); + final boolean state = policyEditorController.getPermission(identifier, perm); for (final JCheckBoxWithGroup jg : groupBoxList) { jg.setState(map); } @@ -999,7 +1094,7 @@ @Override public void actionPerformed(final ActionEvent e) { setChangesMade(true); - policyEditorController.setPermission(codebase, perm, box.isSelected()); + policyEditorController.setPermission(identifier, perm, box.isSelected()); for (JCheckBoxWithGroup jg : groupBoxList) { jg.setState(map); } @@ -1062,6 +1157,8 @@ setMenuItemAccelerator(saveAsItem, R("PESaveAsMenuItemAccelerator")); saveAsItem.addActionListener(editor.saveAsButtonAction); fileMenu.add(saveAsItem); + + fileMenu.addSeparator(); final JMenuItem exitItem = new JMenuItem(R("PEExitMenuItem")); setButtonMnemonic(exitItem, R("PEExitMenuItemMnemonic")); @@ -1070,41 +1167,59 @@ fileMenu.add(exitItem); menuBar.add(fileMenu); - final JMenu codebaseMenu = new JMenu(R("PECodebaseMenu")); - setButtonMnemonic(codebaseMenu, R("PECodebaseMenuMnemonic")); + final JMenu entryMenu = new JMenu(R("PEEntryMenu")); + setButtonMnemonic(entryMenu, R("PEEntryMenuMnemonic")); + + final JMenuItem addEntryItem = new JMenuItem(R("PEAddEntryItem")); + setButtonMnemonic(addEntryItem, R("PEAddEntryItemMnemonic")); + setMenuItemAccelerator(addEntryItem, R("PEAddEntryItemAccelerator")); + addEntryItem.addActionListener(editor.addEntryButtonAction); + entryMenu.add(addEntryItem); - final JMenuItem addNewCodebaseItem = new JMenuItem(R("PEAddCodebaseItem")); - setButtonMnemonic(addNewCodebaseItem, R("PEAddCodebaseItemMnemonic")); - setMenuItemAccelerator(addNewCodebaseItem, R("PEAddCodebaseItemAccelerator")); - addNewCodebaseItem.addActionListener(editor.addCodebaseButtonAction); - codebaseMenu.add(addNewCodebaseItem); + final JMenuItem removeEntryItem = new JMenuItem(R("PERemoveEntryItem")); + setButtonMnemonic(removeEntryItem, R("PERemoveEntryItemMnemonic")); + setMenuItemAccelerator(removeEntryItem, R("PERemoveEntryItemAccelerator")); + removeEntryItem.addActionListener(editor.removeEntryButtonAction); + entryMenu.add(removeEntryItem); + + entryMenu.addSeparator(); - final JMenuItem removeCodebaseItem = new JMenuItem(R("PERemoveCodebaseItem")); - setButtonMnemonic(removeCodebaseItem, R("PERemoveCodebaseItemMnemonic")); - setMenuItemAccelerator(removeCodebaseItem, R("PERemoveCodebaseItemAccelerator")); - removeCodebaseItem.addActionListener(editor.removeCodebaseButtonAction); - codebaseMenu.add(removeCodebaseItem); + final JMenu modifySubmenuItem = new JMenu(R("PEModifySubmenuItem")); + setButtonMnemonic(modifySubmenuItem, R("PEModifySubmenuItemMnemonic")); - codebaseMenu.addSeparator(); + final JMenuItem modifyCodebaseItem = new JMenuItem(R("PEModifyCodebaseItem")); + setButtonMnemonic(modifyCodebaseItem, R("PEModifyEntryCodebaseItemMnemonic")); + setMenuItemAccelerator(modifyCodebaseItem, R("PEModifyEntryCodebaseItemAccelerator")); + modifyCodebaseItem.addActionListener(editor.modifyCodebaseButtonAction); + modifySubmenuItem.add(modifyCodebaseItem); - final JMenuItem renameCodebaseItem = new JMenuItem(R("PERenameCodebaseItem")); - setButtonMnemonic(renameCodebaseItem, R("PERenameCodebaseItemMnemonic")); - setMenuItemAccelerator(renameCodebaseItem, R("PERenameCodebaseItemAccelerator")); - renameCodebaseItem.addActionListener(editor.renameCodebaseButtonAction); - codebaseMenu.add(renameCodebaseItem); + final JMenuItem modifyPrincipalsItem = new JMenuItem(R("PEModifyPrincipalsItem")); + setButtonMnemonic(modifyPrincipalsItem, R("PEModifyEntryPrincipalsItemMnemonic")); + setMenuItemAccelerator(modifyPrincipalsItem, R("PEModifyEntryPrincipalsItemAccelerator")); + modifyPrincipalsItem.addActionListener(editor.modifyPrincipalsButtonAction); + modifySubmenuItem.add(modifyPrincipalsItem); + + final JMenuItem modifySignedByItem = new JMenuItem(R("PEModifySignedByItem")); + setButtonMnemonic(modifySignedByItem, R("PEModifyEntrySignedByItemMnemonic")); + setMenuItemAccelerator(modifySignedByItem, R("PEModifyEntrySignedByItemAccelerator")); + modifySignedByItem.addActionListener(editor.modifySignedByButtonAction); + modifySubmenuItem.add(modifySignedByItem); - final JMenuItem copyCodebaseItem = new JMenuItem(R("PECopyCodebaseItem")); - setButtonMnemonic(copyCodebaseItem, R("PECopyCodebaseItemMnemonic")); - setMenuItemAccelerator(copyCodebaseItem, R("PECopyCodebaseItemAccelerator")); - copyCodebaseItem.addActionListener(editor.copyCodebaseButtonAction); - codebaseMenu.add(copyCodebaseItem); - menuBar.add(codebaseMenu); + entryMenu.add(modifySubmenuItem); + entryMenu.addSeparator(); - final JMenuItem pasteCodebaseItem = new JMenuItem(R("PEPasteCodebaseItem")); - setButtonMnemonic(pasteCodebaseItem, R("PEPasteCodebaseItemMnemonic")); - setMenuItemAccelerator(pasteCodebaseItem, R("PEPasteCodebaseItemAccelerator")); - pasteCodebaseItem.addActionListener(editor.pasteCodebaseButtonAction); - codebaseMenu.add(pasteCodebaseItem); + final JMenuItem copyEntryItem = new JMenuItem(R("PECopyEntryItem")); + setButtonMnemonic(copyEntryItem, R("PECopyEntryItemMnemonic")); + setMenuItemAccelerator(copyEntryItem, R("PECopyEntryItemAccelerator")); + copyEntryItem.addActionListener(editor.copyEntryButtonAction); + entryMenu.add(copyEntryItem); + menuBar.add(entryMenu); + + final JMenuItem pasteEntryItem = new JMenuItem(R("PEPasteEntryItem")); + setButtonMnemonic(pasteEntryItem, R("PEPasteEntryItemMnemonic")); + setMenuItemAccelerator(pasteEntryItem, R("PEPasteEntryItemAccelerator")); + pasteEntryItem.addActionListener(editor.pasteEntryButtonAction); + entryMenu.add(pasteEntryItem); final JMenu viewMenu = new JMenu(R("PEViewMenu")); setButtonMnemonic(viewMenu, R("PEViewMenuMnemonic")); @@ -1146,21 +1261,21 @@ final Action listCopyOverrideAction = new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { - editor.copyCodebaseButtonAction.actionPerformed(e); + editor.copyEntryButtonAction.actionPerformed(e); } }; final Action listPasteOverrideAction = new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { - editor.pasteCodebaseButtonAction.actionPerformed(e); + editor.pasteEntryButtonAction.actionPerformed(e); } }; - listInputMap.put(copyCodebaseItem.getAccelerator(), "CopyCodebaseOverride"); - listActionMap.put("CopyCodebaseOverride", listCopyOverrideAction); - listInputMap.put(pasteCodebaseItem.getAccelerator(), "PasteCodebaseOverride"); - listActionMap.put("PasteCodebaseOverride", listPasteOverrideAction); + listInputMap.put(copyEntryItem.getAccelerator(), "CopyEntryOverride"); + listActionMap.put("CopyEntryOverride", listCopyOverrideAction); + listInputMap.put(pasteEntryItem.getAccelerator(), "PasteEntryOverride"); + listActionMap.put("PasteEntryOverride", listPasteOverrideAction); return menuBar; } @@ -1199,17 +1314,17 @@ checkboxConstraints.gridy++; } } - //add groups + // add groups for (final PolicyEditorPermissions.Group g : PolicyEditorPermissions.Group.values()) { - //no metter what, put group title on new line + // no matter what, put group title on new line checkboxConstraints.gridy++; - //all groups are in second column + // all groups are in second column checkboxConstraints.gridx = 2; final JCheckBoxWithGroup groupCh = new JCheckBoxWithGroup(g); groupBoxList.add(groupCh); final JPanel groupPanel = new JPanel(new GridBagLayout()); groupPanel.setBorder(new LineBorder(Color.black)); - groupCh.setToolTipText(R("PEGrightClick")); + groupCh.setToolTipText(R("PEGRightClick")); groupCh.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { @@ -1229,8 +1344,8 @@ groupCh.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - final String codebase = getSelectedCodebase(); - if (codebase == null) { + final PolicyIdentifier identifier = getSelectedPolicyIdentifier(); + if (identifier == null) { return; } List<ActionListener> backup = new LinkedList<>(); @@ -1239,10 +1354,10 @@ groupCh.removeActionListener(l); } for (final PolicyEditorPermissions p : groupCh.getGroup().getPermissions()) { - policyEditorController.setPermission(codebase, p, groupCh.isSelected()); + policyEditorController.setPermission(identifier, p, groupCh.isSelected()); } setChangesMade(true); - updateCheckboxes(codebase); + updateCheckboxes(identifier); for (final ActionListener al : backup) { groupCh.addActionListener(al); } @@ -1273,17 +1388,17 @@ } } groupPanel.setVisible(false); - //reset + // reset checkboxConstraints.gridwidth = 1; } - final JLabel codebaseListLabel = new JLabel(R("PECodebaseLabel")); - codebaseListLabel.setBorder(new EmptyBorder(2, 2, 2, 2)); + final JLabel entriesListLabel = new JLabel(R("PEEntriesLabel")); + entriesListLabel.setBorder(new EmptyBorder(2, 2, 2, 2)); final GridBagConstraints listLabelConstraints = new GridBagConstraints(); listLabelConstraints.fill = GridBagConstraints.HORIZONTAL; listLabelConstraints.gridx = 0; listLabelConstraints.gridy = 0; - add(codebaseListLabel, listLabelConstraints); + add(entriesListLabel, listLabelConstraints); list.addListSelectionListener(new ListSelectionListener() { @Override @@ -1291,11 +1406,7 @@ if (e.getValueIsAdjusting()) { return; // ignore first click, act on release } - final String codebase = getSelectedCodebase(); - if (codebase == null) { - return; - } - updateCheckboxes(codebase); + updateCheckboxes(getSelectedPolicyIdentifier()); } }); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -1313,25 +1424,25 @@ listConstraints.gridy = 1; add(scrollPane, listConstraints); - final GridBagConstraints addCodebaseButtonConstraints = new GridBagConstraints(); - addCodebaseButtonConstraints.fill = GridBagConstraints.HORIZONTAL; - addCodebaseButtonConstraints.gridx = 0; - addCodebaseButtonConstraints.gridy = listConstraints.gridy + listConstraints.gridheight + 1; - setButtonMnemonic(addCodebaseButton, R("PEAddCodebaseMnemonic")); - add(addCodebaseButton, addCodebaseButtonConstraints); + final GridBagConstraints addEntryButtonConstraints = new GridBagConstraints(); + addEntryButtonConstraints.fill = GridBagConstraints.HORIZONTAL; + addEntryButtonConstraints.gridx = 0; + addEntryButtonConstraints.gridy = listConstraints.gridy + listConstraints.gridheight + 1; + setButtonMnemonic(addEntryButton, R("PEAddEntryMnemonic")); + add(addEntryButton, addEntryButtonConstraints); - final GridBagConstraints removeCodebaseButtonConstraints = new GridBagConstraints(); - removeCodebaseButtonConstraints.fill = GridBagConstraints.HORIZONTAL; - removeCodebaseButtonConstraints.gridx = addCodebaseButtonConstraints.gridx + 1; - removeCodebaseButtonConstraints.gridy = addCodebaseButtonConstraints.gridy; - setButtonMnemonic(removeCodebaseButton, R("PERemoveCodebaseMnemonic")); - removeCodebaseButton.setPreferredSize(addCodebaseButton.getPreferredSize()); - add(removeCodebaseButton, removeCodebaseButtonConstraints); + final GridBagConstraints removeEntryButtonConstraints = new GridBagConstraints(); + removeEntryButtonConstraints.fill = GridBagConstraints.HORIZONTAL; + removeEntryButtonConstraints.gridx = addEntryButtonConstraints.gridx + 1; + removeEntryButtonConstraints.gridy = addEntryButtonConstraints.gridy; + setButtonMnemonic(removeEntryButton, R("PERemoveEntryMnemonic")); + removeEntryButton.setPreferredSize(addEntryButton.getPreferredSize()); + add(removeEntryButton, removeEntryButtonConstraints); final GridBagConstraints okButtonConstraints = new GridBagConstraints(); okButtonConstraints.fill = GridBagConstraints.HORIZONTAL; - okButtonConstraints.gridx = removeCodebaseButtonConstraints.gridx + 2; - okButtonConstraints.gridy = removeCodebaseButtonConstraints.gridy; + okButtonConstraints.gridx = removeEntryButtonConstraints.gridx + 2; + okButtonConstraints.gridy = removeEntryButtonConstraints.gridy; add(okButton, okButtonConstraints); final GridBagConstraints cancelButtonConstraints = new GridBagConstraints(); @@ -1353,28 +1464,57 @@ }); } - private void resetCodebases() { + private void resetEntries() { listModel.clear(); - policyEditorController.clearPermissions(); - policyEditorController.clearCustomPermissions(); + policyEditorController.clear(); } /** * @return whether this PolicyEditor is currently opening or saving a policy file to disk */ public boolean isPerformingIO() { - return policyEditorController.performingIO(); + return policyEditorController.isPerformingIO(); } - private void openAndParsePolicyFile() { - resetCodebases(); + public void openPolicyFileSynchronously() { + if (getFile() == null) { + return; + } + resetEntries(); + final OpenFileResult ofr = FileUtils.testFilePermissions(getFile()); + if (ofr == OpenFileResult.FAILURE || ofr == OpenFileResult.NOT_FILE) { + addDefaultAllAppletsIdentifier(); + OutputController.getLogger().log(R("PECouldNotOpen")); + } + if (ofr == OpenFileResult.CANT_WRITE) { + OutputController.getLogger().log(R("RFileReadOnly")); + } + try { - policyEditorController.getFile().createNewFile(); - } catch (final IOException e) { + policyEditorController.openAndParsePolicyFile(); + } catch (IOException | PolicyParser.ParsingException e) { OutputController.getLogger().log(e); + return; } - final OpenFileResult ofr = FileUtils.testFilePermissions(policyEditorController.getFile()); + + for (final PolicyIdentifier identifier : policyEditorController.getIdentifiers()) { + if (!listModel.contains(identifier)) { + listModel.addElement(identifier); + } + } + addDefaultAllAppletsIdentifier(); + updateCheckboxes(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); + setChangesMade(false); + } + + public void openAndParsePolicyFile() { + if (getFile() == null) { + return; + } + resetEntries(); + final OpenFileResult ofr = FileUtils.testFilePermissions(getFile()); if (ofr == OpenFileResult.FAILURE || ofr == OpenFileResult.NOT_FILE) { + addDefaultAllAppletsIdentifier(); FileUtils.showCouldNotOpenFilepathDialog(PolicyEditor.this, policyEditorController.getFile().getPath()); return; } @@ -1382,7 +1522,6 @@ FileUtils.showReadOnlyDialog(PolicyEditor.this); } - final Window parentWindow = SwingUtilities.getWindowAncestor(this); final JDialog progressIndicator = new IndeterminateProgressDialog(parentWindow, "Loading..."); final SwingWorker<Void, Void> openPolicyFileWorker = new SwingWorker<Void, Void>() { @@ -1402,7 +1541,7 @@ } catch (final FileNotFoundException fnfe) { OutputController.getLogger().log(fnfe); FileUtils.showCouldNotOpenDialog(PolicyEditor.this, R("PECouldNotOpen")); - } catch (final IOException | InvalidPolicyException e) { + } catch (final IOException | PolicyParser.ParsingException e) { OutputController.getLogger().log(e); OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RCantOpenFile", policyEditorController.getFile().getPath())); FileUtils.showCouldNotOpenDialog(PolicyEditor.this, R("PECouldNotOpen")); @@ -1412,18 +1551,13 @@ @Override public void done() { - for (final String codebase : policyEditorController.getCodebases()) { - final String model; - if (codebase.isEmpty()) { - model = R("PEGlobalSettings"); - } else { - model = codebase; - } - if (!listModel.contains(model)) { - listModel.addElement(model); + for (final PolicyIdentifier identifier : policyEditorController.getIdentifiers()) { + if (!listModel.contains(identifier)) { + listModel.addElement(identifier); } } - addNewCodebase(""); + addDefaultAllAppletsIdentifier(); + updateCheckboxes(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); progressIndicator.setVisible(false); progressIndicator.dispose(); setChangesMade(false); @@ -1522,11 +1656,11 @@ }); } - private void showInvalidPolicyExceptionDialog(final String codebase) { + private void showInvalidPolicyExceptionDialog(final PolicyIdentifier identifier) { invokeRunnableOrEnqueueLater(new Runnable() { @Override public void run() { - JOptionPane.showMessageDialog(parentPolicyEditor.get(), R("PEInvalidPolicy", codebase), R("Error"), JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(parentPolicyEditor.get(), R("PEInvalidPolicy", identifier.toString()), R("Error"), JOptionPane.ERROR_MESSAGE); } }); } @@ -1546,7 +1680,6 @@ * @return The user's choice (Yes/No/Cancel - see JOptionPane constants). * "Cancel" if the file hasn't changed but the user has made modifications * to the settings. "No" otherwise - * @throws IOException if the file cannot be read */ private int checkPolicyChangesWithDialog() { boolean changed; @@ -1591,9 +1724,6 @@ * @param args "-file $FILENAME" and/or "-codebase $CODEBASE" are accepted flag/value pairs. * -file specifies a file path to be opened by the editor. If none is provided, the default * policy file location for the user is opened. - * -codebase specifies (a) codebase(s) to start the editor with. If the entry already exists, - * it will be selected. If it does not exist, it will be created, then selected. Multiple - * codebases can be used, separated by spaces. * -help will print a help message and immediately return (no editor instance opens) */ public static void main(final String[] args) { @@ -1629,20 +1759,24 @@ @Override public void run() { String filepath = optionParser.getParam(OptionsDefinitions.OPTIONS.FILE); - if (filepath.isEmpty()) { - if (optionParser.getMainArgs().size() == 0) { - filepath = null; - } else { - // maybe the user just forgot the -file flag, so try to open anyway - filepath = optionParser.getMainArg(); - } + if (filepath == null || filepath.isEmpty() || filepath.trim().isEmpty()) { + // maybe the user just forgot the -file flag, so try to open anyway + filepath = optionParser.getMainArg(); + } + if (filepath == null || filepath.isEmpty() || filepath.trim().isEmpty()) { + filepath = null; } final PolicyEditorWindow frame = getPolicyEditorFrame(filepath); + final String codebase = optionParser.getParam(OptionsDefinitions.OPTIONS.CODEBASE); + final String signedBy = optionParser.getParam(OptionsDefinitions.OPTIONS.SIGNEDBY); + final List<String> rawPrincipals = optionParser.getParams(OptionsDefinitions.OPTIONS.PRINCIPALS); + final Set<PolicyParser.PrincipalEntry> principals = new HashSet<>(); + for (int i = 0; i < rawPrincipals.size(); i+= 2) { + principals.add(new PolicyParser.PrincipalEntry(rawPrincipals.get(i), rawPrincipals.get(i + 1))); + } + frame.getPolicyEditor().openPolicyFileSynchronously(); + frame.getPolicyEditor().addNewEntry(new PolicyIdentifier(signedBy, principals, codebase)); frame.asWindow().setVisible(true); - final List<String> codebases = optionParser.getParams(OptionsDefinitions.OPTIONS.CODEBASE); - for (final String url : codebases) { - frame.getPolicyEditor().addNewCodebase(url); - } } }); }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorController.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorController.java Thu Jul 30 10:57:21 2015 -0400 @@ -37,21 +37,22 @@ package net.sourceforge.jnlp.security.policyeditor; import java.awt.Toolkit; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import net.sourceforge.jnlp.util.logging.OutputController; +import sun.security.provider.PolicyParser; + +import static net.sourceforge.jnlp.security.policyeditor.PolicyEntry.POLICY_ENTRY_DATA_FLAVOR; public class PolicyEditorController { @@ -67,7 +68,7 @@ changesMade = b; } - boolean performingIO() { + boolean isPerformingIO() { return performingIO; } @@ -76,53 +77,58 @@ } public void setFile(final File file) { - setChangesMade(true); - policyFile.setFile(file); + boolean changedFile = policyFile.setFile(file); + setChangesMade(changedFile); } public File getFile() { return policyFile.getFile(); } - public boolean fileHasChanged() throws FileNotFoundException, IOException { + public boolean fileHasChanged() throws IOException { return policyFile.hasChanged(); } - public boolean addCodebase(final String codebase) { - final boolean existed = policyFile.addCodebase(codebase); + public boolean addIdentifier(final PolicyIdentifier identifier) { + final boolean existed = policyFile.addIdentifier(identifier); if (!existed) { setChangesMade(true); } return existed; } - public void removeCodebase(final String codebase) { + public void removeIdentifier(final PolicyIdentifier identifier) { setChangesMade(true); - policyFile.removeCodebase(codebase); + policyFile.removeIdentifier(identifier); } - public Set<String> getCodebases() { - return new HashSet<>(policyFile.getCodebases()); + public Set<PolicyIdentifier> getIdentifiers() { + return new HashSet<>(policyFile.getIdentifiers()); } - public Map<String, Map<PolicyEditorPermissions, Boolean>> getCopyOfPermissions() { + public Map<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>> getCopyOfPermissions() { return policyFile.getCopyOfPermissions(); } - public void setPermission(final String codebase, final PolicyEditorPermissions permission, final boolean state) { - if (getPermission(codebase, permission) != state) { + public void setPermission(final PolicyIdentifier identifier, final PolicyEditorPermissions permission, final boolean state) { + if (getPermission(identifier, permission) != state) { setChangesMade(true); } - policyFile.setPermission(codebase, permission, state); + policyFile.setPermission(identifier, permission, state); } - public boolean getPermission(final String codebase, final PolicyEditorPermissions permission) { - return policyFile.getPermission(codebase, permission); + public boolean getPermission(final PolicyIdentifier identifier, final PolicyEditorPermissions permission) { + return policyFile.getPermission(identifier, permission); } - public Map<PolicyEditorPermissions, Boolean> getPermissions(final String codebase) { - policyFile.addCodebase(codebase); - return new HashMap<>(policyFile.getCopyOfPermissions().get(codebase)); + public Map<PolicyEditorPermissions, Boolean> getPermissions(final PolicyIdentifier identifier) { + policyFile.addIdentifier(identifier); + return new HashMap<>(policyFile.getCopyOfPermissions().get(identifier)); + } + + public void clear() { + setChangesMade(true); + policyFile.clearPermissions(); } public void clearPermissions() { @@ -130,32 +136,32 @@ policyFile.clearPermissions(); } - public void addCustomPermissions(final String codebase, final Collection<CustomPermission> permissions) { - if (!policyFile.getCopyOfCustomPermissions().equals(permissions)) { + public void addCustomPermissions(final PolicyIdentifier identifier, final Collection<PolicyParser.PermissionEntry> permissions) { + if (!policyFile.getCopyOfCustomPermissions().containsKey(identifier) || !policyFile.getCopyOfCustomPermissions().get(identifier).equals(permissions)) { setChangesMade(true); } - policyFile.addCustomPermissions(codebase, permissions); + policyFile.addCustomPermissions(identifier, permissions); } - public void addCustomPermission(final String codebase, final CustomPermission permission) { - final Map<String, Set<CustomPermission>> customs = policyFile.getCopyOfCustomPermissions(); - if (customs == null || !customs.containsKey(codebase) || (customs.containsKey(codebase) && !customs.get(codebase).contains(permission))) { + public void addCustomPermission(final PolicyIdentifier identifier, final PolicyParser.PermissionEntry permission) { + final Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> customs = policyFile.getCopyOfCustomPermissions(); + if (customs == null || !customs.containsKey(identifier) || (customs.containsKey(identifier) && !customs.get(identifier).contains(permission))) { setChangesMade(true); } - addCustomPermissions(codebase, Arrays.asList(permission)); + addCustomPermissions(identifier, Collections.singletonList(permission)); } - public Set<CustomPermission> getCustomPermissions(final String codebase) { - policyFile.addCodebase(codebase); - return new HashSet<>(policyFile.getCopyOfCustomPermissions().get(codebase)); + public Set<PolicyParser.PermissionEntry> getCustomPermissions(final PolicyIdentifier identifier) { + policyFile.addIdentifier(identifier); + return new HashSet<>(policyFile.getCopyOfCustomPermissions().get(identifier)); } public void addPolicyEntry(final PolicyEntry policyEntry) { - addCodebase(policyEntry.getCodebase()); + addIdentifier(policyEntry.getPolicyIdentifier()); for (final PolicyEditorPermissions permission : policyEntry.getPermissions()) { - setPermission(policyEntry.getCodebase(), permission, true); + setPermission(policyEntry.getPolicyIdentifier(), permission, true); } - addCustomPermissions(policyEntry.getCodebase(), policyEntry.getCustomPermissions()); + addCustomPermissions(policyEntry.getPolicyIdentifier(), policyEntry.getCustomPermissions()); } public void clearCustomPermissions() { @@ -163,18 +169,12 @@ policyFile.clearCustomPermissions(); } - public void clearCustomCodebase(final String codebase) { + public void clearCustomIdentifier(final PolicyIdentifier identifier) { setChangesMade(true); - policyFile.clearCustomCodebase(codebase); + policyFile.clearCustomIdentifier(identifier); } - public void openAndParsePolicyFile() throws IOException, InvalidPolicyException { - try { - policyFile.getFile().createNewFile(); - } catch (final IOException e) { - OutputController.getLogger().log(e); - } - + public void openAndParsePolicyFile() throws IOException, PolicyParser.ParsingException { setPerformingIO(true); policyFile.openAndParsePolicyFile(); @@ -182,7 +182,7 @@ setPerformingIO(false); } - public void savePolicyFile() throws FileNotFoundException, IOException { + public void savePolicyFile() throws IOException { setPerformingIO(true); policyFile.savePolicyFile(); @@ -190,45 +190,29 @@ setPerformingIO(false); } - public void copyCodebaseToClipboard(final String codebase) { - final Map<PolicyEditorPermissions, Boolean> standardPermissions = policyFile.getCopyOfPermissions().get(codebase); - final Set<CustomPermission> customPermissions = policyFile.getCopyOfCustomPermissions().get(codebase); + public void copyPolicyEntryToClipboard(final PolicyIdentifier identifier) { + final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + final PolicyEntry policyEntry = getPolicyEntry(identifier); + clipboard.setContents(policyEntry, null); + } - final Set<PolicyEditorPermissions> enabledPermissions = new HashSet<>(); - for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : standardPermissions.entrySet()) { + public PolicyEntry getPolicyEntry(final PolicyIdentifier identifier) { + final Collection<PolicyEditorPermissions> enabledPermissions = new HashSet<>(); + for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : getPermissions(identifier).entrySet()) { if (entry.getValue()) { enabledPermissions.add(entry.getKey()); } } - final PolicyEntry entry = new PolicyEntry(codebase, enabledPermissions, customPermissions); - final StringSelection clipboardSelection = new StringSelection(entry.toString()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboardSelection, clipboardSelection); - } - - private static String getClipboardContentsAsString() throws IOException, UnsupportedFlavorException { - final Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); - return (String) transferable.getTransferData(DataFlavor.stringFlavor); - } - - public static PolicyEntry getPolicyEntryFromClipboard() throws IOException, UnsupportedFlavorException, InvalidPolicyException { - return PolicyEntry.fromString(getClipboardContentsAsString()); + return new PolicyEntry.Builder() + .identifier(identifier) + .permissions(enabledPermissions) + .customPermissions(getCustomPermissions(identifier)) + .build(); } - public String getCodebaseFromClipboard() throws IOException, UnsupportedFlavorException, InvalidPolicyException { - return getPolicyEntryFromClipboard().getCodebase(); - } - - public Map<PolicyEditorPermissions, Boolean> getPermissionsFromClipboard() throws IOException, UnsupportedFlavorException, InvalidPolicyException { - final Map<PolicyEditorPermissions, Boolean> ret = new HashMap<>(); - final Set<PolicyEditorPermissions> enabledPermissions = getPolicyEntryFromClipboard().getPermissions(); - for (final PolicyEditorPermissions permission : PolicyEditorPermissions.values()) { - ret.put(permission, enabledPermissions.contains(permission)); - } - return ret; - } - - public Set<CustomPermission> getCustomPermissionsFromClipboard() throws IOException, UnsupportedFlavorException, InvalidPolicyException { - return getPolicyEntryFromClipboard().getCustomPermissions(); + public static PolicyEntry getPolicyEntryFromClipboard() throws IOException, UnsupportedFlavorException, PolicyParser.ParsingException { + final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + return (PolicyEntry) clipboard.getContents(null).getTransferData(POLICY_ENTRY_DATA_FLAVOR); } }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,6 +36,9 @@ package net.sourceforge.jnlp.security.policyeditor; +import sun.security.provider.PolicyParser; + +import java.io.Serializable; import java.util.Map; import javax.swing.JCheckBox; import static net.sourceforge.jnlp.runtime.Translator.R; @@ -45,7 +48,7 @@ * Defines the set of default permissions for PolicyEditor, ie the ones which are assigned * dedicated checkboxes */ -public enum PolicyEditorPermissions { +public enum PolicyEditorPermissions implements Serializable { READ_LOCAL_FILES(R("PEReadFiles"), R("PEReadFilesDetail"), PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.READ), @@ -123,7 +126,7 @@ ReadFileSystem(R("PEGReadFileSystem"), READ_LOCAL_FILES, READ_PROPERTIES, READ_SYSTEM_FILES, READ_TMP_FILES, GET_ENV), WriteFileSystem(R("PEGWriteFileSystem"), WRITE_LOCAL_FILES, DELETE_LOCAL_FILES, WRITE_PROPERTIES, WRITE_SYSTEM_FILES, WRITE_TMP_FILES, DELETE_TMP_FILES, EXEC_COMMANDS), - AccessUnownedCode(R("PEGAccesUnowenedCode"), JAVA_REFLECTION, GET_CLASSLOADER, ACCESS_CLASS_IN_PACKAGE, ACCESS_DECLARED_MEMBERS, ACCESS_THREADS, ACCESS_THREAD_GROUPS), + AccessUnownedCode(R("PEGAccessUnownedCode"), JAVA_REFLECTION, GET_CLASSLOADER, ACCESS_CLASS_IN_PACKAGE, ACCESS_DECLARED_MEMBERS, ACCESS_THREADS, ACCESS_THREAD_GROUPS), MediaAccess(R("PEGMediaAccess"), PLAY_AUDIO, RECORD_AUDIO, PRINT, CLIPBOARD); private final PolicyEditorPermissions[] permissions; @@ -161,15 +164,15 @@ * 0 invalid * - none is selected */ - public int getState (final Map<PolicyEditorPermissions, Boolean> map) { + public int getState(final Map<PolicyEditorPermissions, Boolean> map) { boolean allTrue = true; boolean allFalse = true; for (final PolicyEditorPermissions pp : getPermissions()) { final Boolean b = map.get(pp); - if (b == null){ + if (b == null) { return 0; } - if (b.booleanValue()){ + if (b) { allFalse = false; } else { allTrue = false; @@ -283,28 +286,18 @@ return string.replaceAll("[\\[\\]\\s]", ""); } - /** - * Get a PolicyEditorPermissions instance matching the input string - * @param string a full policy file permissions line, eg `permission java.io.FilePermission "${io.tmpdir}" "read;"` - * @return the PolicyEditorPermissions value matching the input String, or null if no such match is found - */ - public static PolicyEditorPermissions fromString(final String string) { - final CustomPermission tmpPerm = CustomPermission.fromString(string); - if (tmpPerm == null) { - return null; - } - - final PermissionType type = PermissionType.fromString(tmpPerm.type); - final PermissionTarget target = PermissionTarget.fromString(tmpPerm.target); - final PermissionActions actions = PermissionActions.fromString(tmpPerm.actions); - - for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { - final boolean sameType = perm.type.equals(type); - final boolean sameTarget = perm.target.equals(target); - final boolean sameActions = perm.actions.getActions().equals(actions.getActions()); - - if (sameType && sameTarget && sameActions) { - return perm; + public static PolicyEditorPermissions fromPermissionEntry(final PolicyParser.PermissionEntry permissionEntry) { + for (final PolicyEditorPermissions permission : values()) { + final String actionsString; + if (permission.getActions().equals(PermissionActions.NONE)) { + actionsString = null; + } else { + actionsString = permission.getActions().rawString(); + } + final PolicyParser.PermissionEntry editorEntry = + new PolicyParser.PermissionEntry(permission.getType().type, permission.getTarget().target, actionsString); + if (editorEntry.equals(permissionEntry)) { + return permission; } } return null;
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEntry.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEntry.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,165 +36,109 @@ package net.sourceforge.jnlp.security.policyeditor; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.io.Serializable; import java.util.Arrays; import java.util.Collection; +import java.util.EnumSet; import java.util.HashSet; -import java.util.List; +import java.util.Objects; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; +import sun.security.provider.PolicyParser; /** - * This class represents a codebase entry in a policy file. This is defined as a policy entry block - * which begins with they keyword "grant" and ends with the delimiter "};". If the entry - * contains a "codeBase $CODEBASE" substring after the "grant" keyword, then this information - * is also included in this entry. Other entry "metadata" such as Principal is not defined. - * Within a codebase entry block, lines are recognized and modelled as either PolicyEditorPermissions - * or CustomPermissions. + * This class represents a "grant" entry in a policy file. This is defined as a policy entry block + * which begins with the keyword "grant" and ends with the delimiter "};". */ -public class PolicyEntry { +public class PolicyEntry implements Serializable, Transferable { + + public static class Builder { + private String signedBy, codebase; + private final Set<PolicyEditorPermissions> permissions = EnumSet.noneOf(PolicyEditorPermissions.class); + private final Set<PolicyParser.PermissionEntry> customPermissions = new HashSet<>(); + private final Set<PolicyParser.PrincipalEntry> principals = new HashSet<>(); + + public Builder signedBy(final String signedBy) { + this.signedBy = signedBy; + return this; + } + + public Builder principals(final Collection<PolicyParser.PrincipalEntry> principals) { + this.principals.addAll(principals); + return this; + } + + public Builder codebase(final String codebase) { + this.codebase = codebase; + return this; + } - private final String codebase; + public Builder identifier(final PolicyIdentifier identifier) { + return signedBy(identifier.getSignedBy()) + .codebase(identifier.getCodebase()) + .principals(identifier.getPrincipals()); + } + + public Builder permissions(final Collection<PolicyEditorPermissions> permissions) { + this.permissions.addAll(permissions); + return this; + } + + public Builder customPermissions(final Collection<? extends PolicyParser.PermissionEntry> customPermissions) { + this.customPermissions.addAll(customPermissions); + return this; + } + + public PolicyEntry build() { + return new PolicyEntry(this); + } + } + + public static final DataFlavor POLICY_ENTRY_DATA_FLAVOR = new DataFlavor(PolicyEntry.class, "PolicyEntry"); + + private final PolicyIdentifier policyIdentifier; private final Set<PolicyEditorPermissions> permissions = new HashSet<>(); - private final Set<CustomPermission> customPermissions = new HashSet<>(); + private final Set<PolicyParser.PermissionEntry> customPermissions = new HashSet<>(); - public PolicyEntry(final String codebase, final Collection<PolicyEditorPermissions> permissions, - final Collection<CustomPermission> customPermissions) { - if (codebase == null) { - this.codebase = ""; - } else { - this.codebase = codebase; - } - this.permissions.addAll(permissions); + private PolicyEntry(final Builder builder) { + this.policyIdentifier = new PolicyIdentifier(builder.signedBy, builder.principals, builder.codebase); + this.permissions.addAll(builder.permissions); this.permissions.remove(null); - this.customPermissions.addAll(customPermissions); + this.customPermissions.addAll(builder.customPermissions); this.customPermissions.remove(null); } - public String getCodebase() { - return codebase; + public PolicyIdentifier getPolicyIdentifier() { + return policyIdentifier; } public Set<PolicyEditorPermissions> getPermissions() { return permissions; } - public Set<CustomPermission> getCustomPermissions() { + public Set<PolicyParser.PermissionEntry> getCustomPermissions() { return customPermissions; } - public static PolicyEntry fromString(final String contents) throws InvalidPolicyException { - final List<String> lines = Arrays.asList(contents.split("\\r?\\n+")); - if (!validatePolicy(lines)) { - throw new InvalidPolicyException(); - } - - String codebase = ""; - final Set<PolicyEditorPermissions> permissions = new HashSet<>(); - final Set<CustomPermission> customPermissions = new HashSet<>(); - - boolean openBlock = false, commentBlock = false; - for (final String line : lines) { - // Matches eg `grant {` as well as `grant codeBase "http://redhat.com" {` - final Pattern openBlockPattern = Pattern.compile("grant\\s*\"?\\s*(?:codeBase)?\\s*\"?([^\"\\s]*)\"?\\s*\\{"); - final Matcher openBlockMatcher = openBlockPattern.matcher(line); - if (openBlockMatcher.matches()) { - // Codebase URL - codebase = openBlockMatcher.group(1); - openBlock = true; - continue; - } - - // Matches '};', the closing block delimiter, with any amount of whitespace on either side - boolean commentLine = false; - if (line.matches("\\s*\\};\\s*")) { - openBlock = false; - } - // Matches '/*', the start of a block comment - if (line.matches(".*/\\*.*")) { - commentBlock = true; - } - // Matches '*/', the end of a block comment, and '//', a single-line comment - if (line.matches(".*\\*/.*")) { - commentBlock = false; - } - if (line.matches(".*/\\*.*") && line.matches(".*\\*/.*")) { - commentLine = true; - } - if (line.matches("\\s*//.*")) { - commentLine = true; - } - - if (!openBlock || commentBlock || commentLine) { - continue; - } - - final PolicyEditorPermissions perm = PolicyEditorPermissions.fromString(line); - if (perm != null) { - permissions.add(perm); - } else { - final CustomPermission cPerm = CustomPermission.fromString(line.trim()); - if (cPerm != null) { - customPermissions.add(cPerm); - } - } - } - return new PolicyEntry(codebase, permissions, customPermissions); - } - - public static boolean validatePolicy(final String content) { - return validatePolicy(Arrays.asList(content.split("\\r?\\n"))); - } - - public static boolean validatePolicy(final List<String> lines) { - int openerCount = 0, closerCount = 0; - for (final String line : lines) { - final Pattern openBlockPattern = Pattern.compile("grant\\s*\"?\\s*(?:codeBase)?\\s*\"?([^\"\\s]*)\"?\\s*\\{"); - final Matcher openBlockMatcher = openBlockPattern.matcher(line); - if (openBlockMatcher.matches()) { - ++openerCount; - } - - if (line.matches("\\s*\\};\\s*")) { - ++closerCount; - } - } - return (openerCount == 1) && (closerCount == 1); + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { POLICY_ENTRY_DATA_FLAVOR }; } @Override - public String toString() { - // Empty codebase is the default "All Applets" codebase. If there are no permissions - // applied to it, then don't bother recording it in the policy file. - if (codebase.isEmpty() && permissions.isEmpty() && customPermissions.isEmpty()) { - return ""; - } - final String newline = PlainTextFormatter.getLineSeparator(); - final StringBuilder result = new StringBuilder(); + public boolean isDataFlavorSupported(final DataFlavor dataFlavor) { + return Objects.equals(POLICY_ENTRY_DATA_FLAVOR, dataFlavor); + } - result.append(newline); - result.append("grant"); - if (!codebase.isEmpty()) { - result.append(" codeBase \""); - result.append(codebase); - result.append("\""); + @Override + public Object getTransferData(final DataFlavor dataFlavor) throws UnsupportedFlavorException, IOException { + if (!Arrays.asList(getTransferDataFlavors()).contains(dataFlavor)) { + throw new UnsupportedFlavorException(dataFlavor); } - result.append(" {"); - result.append(newline); - for (final PolicyEditorPermissions perm : permissions) { - result.append("\t"); - result.append(perm.toPermissionString()); - result.append(newline); - } - for (final CustomPermission customPerm : customPermissions) { - result.append("\t"); - result.append(customPerm.toString().trim()); - result.append(newline); - } - result.append("};"); - result.append(newline); - return result.toString(); + return this; } }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyFileModel.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyFileModel.java Thu Jul 30 10:57:21 2015 -0400 @@ -37,11 +37,10 @@ package net.sourceforge.jnlp.security.policyeditor; import java.io.File; -import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.nio.channels.FileLock; -import java.text.SimpleDateFormat; -import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -49,27 +48,28 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.MD5SumWatcher; -import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; import net.sourceforge.jnlp.util.logging.OutputController; +import sun.security.provider.PolicyParser; + +import static net.sourceforge.jnlp.security.policyeditor.PolicyIdentifier.isDefaultPolicyIdentifier; public class PolicyFileModel { - private static final String AUTOGENERATED_NOTICE = "/* DO NOT MODIFY! AUTO-GENERATED */"; - private File file; /** * Maps Codebases to Maps of Permissions and whether that Permission is set or not. The Codebase keys correspond to * the Codebases in the list UI, and the Permission->Boolean maps correspond to the checkboxes associated with * each Codebase. */ - public final Map<String, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap = Collections.synchronizedMap(new HashMap<String, Map<PolicyEditorPermissions, Boolean>>()); - private final Map<String, Set<CustomPermission>> customPermissionsMap = Collections.synchronizedMap(new HashMap<String, Set<CustomPermission>>()); + private final Map<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>> permissionsMap = Collections.synchronizedMap(new HashMap<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>>()); + private final Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> customPermissionsMap = Collections.synchronizedMap(new HashMap<PolicyIdentifier, Set<PolicyParser.PermissionEntry>>()); + + private KeystoreInfo keystoreInfo = new KeystoreInfo(null, null, null, null); private MD5SumWatcher fileWatcher; + private PolicyParser parser = new PolicyParser(false); PolicyFileModel(final String filepath) { this(new File(filepath)); @@ -82,38 +82,51 @@ PolicyFileModel() { } - synchronized void setFile(final File file) { + synchronized boolean setFile(final File file) { this.file = file; + boolean sameFile = Objects.equals(this.file, file); + return !sameFile; } synchronized File getFile() { return file; } + synchronized PolicyParser getParser() { + return parser; + } + /** * Open the file pointed to by the filePath field. This is either provided by the * "-file" command line flag, or if none given, comes from DeploymentConfiguration. */ - synchronized void openAndParsePolicyFile() throws IOException, InvalidPolicyException { + synchronized void openAndParsePolicyFile() throws IOException, PolicyParser.ParsingException { + parser = new PolicyParser(false); fileWatcher = new MD5SumWatcher(file); fileWatcher.update(); - codebasePermissionsMap.clear(); - customPermissionsMap.clear(); + clearPermissions(); final FileLock fileLock = FileUtils.getFileLock(file.getAbsolutePath(), false, true); try { - // User-level policy files are expected to be short enough that loading them in as a String - // should not actually be *too* bad, and it's easy to work with. - final String contents = FileUtils.loadFileAsString(file); - - final Set<PolicyEntry> entries = parsePolicyString(contents); - synchronized (codebasePermissionsMap) { + parser.read(new FileReader(file)); + keystoreInfo = new KeystoreInfo(parser.getKeyStoreUrl(), parser.getKeyStoreType(), parser.getKeyStoreProvider(), parser.getStorePassURL()); + final Set<PolicyParser.GrantEntry> grantEntries = new HashSet<>(Collections.list(parser.grantElements())); + synchronized (permissionsMap) { synchronized (customPermissionsMap) { - for (final PolicyEntry entry : entries) { - addCodebase(entry.getCodebase()); - for (final PolicyEditorPermissions permission : entry.getPermissions()) { - setPermission(entry.getCodebase(), permission, true); + for (final PolicyParser.GrantEntry grantEntry : grantEntries) { + PolicyIdentifier policyIdentifier = + new PolicyIdentifier(grantEntry.signedBy, grantEntry.principals, grantEntry.codeBase); + if (isDefaultPolicyIdentifier(policyIdentifier)) { + policyIdentifier = PolicyIdentifier.ALL_APPLETS_IDENTIFIER; } - addCustomPermissions(entry.getCodebase(), entry.getCustomPermissions()); + addIdentifier(policyIdentifier); + for (final PolicyParser.PermissionEntry permissionEntry : grantEntry.permissionEntries) { + final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.fromPermissionEntry(permissionEntry); + if (editorPermissions != null) { + permissionsMap.get(policyIdentifier).put(editorPermissions, true); + } else { + customPermissionsMap.get(policyIdentifier).add(permissionEntry); + } + } } } } @@ -126,63 +139,48 @@ } } - static Set<PolicyEntry> parsePolicyString(final String contents) throws InvalidPolicyException { - final Set<PolicyEntry> policyEntries = new HashSet<>(); - StringBuilder sb = new StringBuilder(); - - // Split on newlines, both \r\n and \n style, for platform-independence - final String[] lines = contents.split("\\r?\\n+"); - boolean openBlock = false, closeBlock = false; - for (final String line : lines) { - // Matches eg `grant {` as well as `grant codeBase "http://redhat.com" {` - final Pattern openBlockPattern = Pattern.compile("grant\\s*\"?\\s*(?:codeBase)?\\s*\"?[^\"\\s]*\"?\\s*\\{"); - final Matcher openBlockMatcher = openBlockPattern.matcher(line); - if (openBlockMatcher.matches()) { - openBlock = true; - } - - // Matches '};', the closing block delimiter, with any amount of whitespace on either side - if (line.matches("\\s*\\};\\s*")) { - closeBlock = true; - } - - if (openBlock) { - sb.append(line); - sb.append('\n'); - } - - if (openBlock && closeBlock) { - openBlock = closeBlock = false; - policyEntries.add(PolicyEntry.fromString(sb.toString())); - sb = new StringBuilder(); - } - } - return policyEntries; - } - /** * Save the policy model into the file pointed to by the filePath field. */ - synchronized void savePolicyFile() throws FileNotFoundException, IOException { - final StringBuilder sb = new StringBuilder(); - sb.append(AUTOGENERATED_NOTICE); - final String currentDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); - sb.append("\n/* Generated by PolicyEditor at ").append(currentDate).append(" */"); - sb.append(PlainTextFormatter.getLineSeparator()); + synchronized void savePolicyFile() throws IOException { + parser = new PolicyParser(false); FileLock fileLock = null; try { fileLock = FileUtils.getFileLock(file.getAbsolutePath(), false, true); - synchronized (codebasePermissionsMap) { - for (final String codebase : codebasePermissionsMap.keySet()) { - final Set<PolicyEditorPermissions> enabledPermissions = new HashSet<>(); - for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : codebasePermissionsMap.get(codebase).entrySet()) { + synchronized (permissionsMap) { + for (final PolicyIdentifier identifier : permissionsMap.keySet()) { + final String codebase; + if (identifier.getCodebase().isEmpty()) { + codebase = null; + } else { + codebase = identifier.getCodebase(); + } + final PolicyParser.GrantEntry grantEntry = + new PolicyParser.GrantEntry(identifier.getSignedBy(), codebase); + for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : permissionsMap.get(identifier).entrySet()) { if (entry.getValue()) { - enabledPermissions.add(entry.getKey()); + final PolicyEditorPermissions permission = entry.getKey(); + final String actionsString; + if (permission.getActions().equals(PermissionActions.NONE)) { + actionsString = null; + } else { + actionsString = permission.getActions().rawString(); + } + final PolicyParser.PermissionEntry permissionEntry = + new PolicyParser.PermissionEntry(permission.getType().type, + permission.getTarget().target, + actionsString); + grantEntry.add(permissionEntry); } } - sb.append(new PolicyEntry(codebase, enabledPermissions, customPermissionsMap.get(codebase)).toString()); + for (final PolicyParser.PermissionEntry customPermission : customPermissionsMap.get(identifier)) { + grantEntry.add(customPermission); + } + grantEntry.principals.addAll(identifier.getPrincipals()); + parser.add(grantEntry); } } + parser.write(new FileWriter(file)); } catch (final IOException e) { OutputController.getLogger().log(e); } finally { @@ -195,40 +193,41 @@ } } - - FileUtils.saveFile(sb.toString(), file); fileWatcher = new MD5SumWatcher(file); fileWatcher.update(); } - synchronized boolean hasChanged() throws FileNotFoundException, IOException { + synchronized boolean hasChanged() throws IOException { return fileWatcher != null && fileWatcher.update(); } - synchronized Set<String> getCodebases() { - return new HashSet<>(codebasePermissionsMap.keySet()); + synchronized Set<PolicyIdentifier> getIdentifiers() { + return new HashSet<>(permissionsMap.keySet()); + } + + synchronized KeystoreInfo getKeystoreInfo() { + return keystoreInfo; } /** - * Add a new codebase. No action is taken if the codebase has already been added. - * @param codebase for which a permissions mapping is required - * @return true iff there was already an entry for this codebase + * Add a new identifier. No action is taken if the identifier has already been added. + * @param identifier for which a permissions mapping is required + * @return true iff there was already an entry for this identifier */ - synchronized boolean addCodebase(final String codebase) { - Objects.requireNonNull(codebase); + synchronized boolean addIdentifier(final PolicyIdentifier identifier) { + Objects.requireNonNull(identifier); boolean existingCodebase = true; - if (!codebasePermissionsMap.containsKey(codebase)) { + if (!permissionsMap.containsKey(identifier)) { final Map<PolicyEditorPermissions, Boolean> map = new HashMap<>(); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { map.put(perm, false); } - codebasePermissionsMap.put(codebase, map); + permissionsMap.put(identifier, map); existingCodebase = false; } - if (!customPermissionsMap.containsKey(codebase)) { - final Set<CustomPermission> set = new HashSet<>(); - customPermissionsMap.put(codebase, set); + if (!customPermissionsMap.containsKey(identifier)) { + customPermissionsMap.put(identifier, new HashSet<PolicyParser.PermissionEntry>()); existingCodebase = false; } @@ -236,56 +235,56 @@ } synchronized void clearPermissions() { - codebasePermissionsMap.clear(); + permissionsMap.clear(); clearCustomPermissions(); } - synchronized void removeCodebase(final String codebase) { - Objects.requireNonNull(codebase); - codebasePermissionsMap.remove(codebase); - customPermissionsMap.remove(codebase); + synchronized void removeIdentifier(final PolicyIdentifier identifier) { + Objects.requireNonNull(identifier); + permissionsMap.remove(identifier); + customPermissionsMap.remove(identifier); } - synchronized void setPermission(final String codebase, final PolicyEditorPermissions permission, final boolean state) { - Objects.requireNonNull(codebase); + synchronized void setPermission(final PolicyIdentifier identifier, final PolicyEditorPermissions permission, final boolean state) { + Objects.requireNonNull(identifier); Objects.requireNonNull(permission); - addCodebase(codebase); - codebasePermissionsMap.get(codebase).put(permission, state); + addIdentifier(identifier); + permissionsMap.get(identifier).put(permission, state); } - synchronized boolean getPermission(final String codebase, final PolicyEditorPermissions permission) { - Objects.requireNonNull(codebase); + synchronized boolean getPermission(final PolicyIdentifier identifier, final PolicyEditorPermissions permission) { + Objects.requireNonNull(identifier); Objects.requireNonNull(permission); - if (!codebasePermissionsMap.containsKey(codebase)) { + if (!permissionsMap.containsKey(identifier)) { return false; } - return codebasePermissionsMap.get(codebase).get(permission); + return permissionsMap.get(identifier).get(permission); } - synchronized Map<String, Map<PolicyEditorPermissions, Boolean>> getCopyOfPermissions() { - return new HashMap<>(codebasePermissionsMap); + synchronized Map<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>> getCopyOfPermissions() { + return new HashMap<>(permissionsMap); } synchronized void clearCustomPermissions() { customPermissionsMap.clear(); } - synchronized void clearCustomCodebase(final String codebase) { - Objects.requireNonNull(codebase); - if (!customPermissionsMap.containsKey(codebase)) { + synchronized void clearCustomIdentifier(final PolicyIdentifier identifier) { + Objects.requireNonNull(identifier); + if (!customPermissionsMap.containsKey(identifier)) { return; } - customPermissionsMap.get(codebase).clear(); + customPermissionsMap.get(identifier).clear(); } - synchronized void addCustomPermissions(final String codebase, final Collection<CustomPermission> permissions) { - Objects.requireNonNull(codebase); + synchronized void addCustomPermissions(final PolicyIdentifier identifier, final Collection<? extends PolicyParser.PermissionEntry> permissions) { + Objects.requireNonNull(identifier); Objects.requireNonNull(permissions); - addCodebase(codebase); - customPermissionsMap.get(codebase).addAll(permissions); + addIdentifier(identifier); + customPermissionsMap.get(identifier).addAll(permissions); } - synchronized Map<String, Set<CustomPermission>> getCopyOfCustomPermissions() { + synchronized Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> getCopyOfCustomPermissions() { return new HashMap<>(customPermissionsMap); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyIdentifier.java Thu Jul 30 10:57:21 2015 -0400 @@ -0,0 +1,147 @@ +/*Copyright (C) 2014 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +package net.sourceforge.jnlp.security.policyeditor; + +import net.sourceforge.jnlp.runtime.Translator; +import sun.security.provider.PolicyParser; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +// http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html +public class PolicyIdentifier implements Serializable { + + public static final PolicyIdentifier ALL_APPLETS_IDENTIFIER = new PolicyIdentifier(null, Collections.<PolicyParser.PrincipalEntry>emptySet(), null) { + @Override + public String toString() { + return Translator.R("PEGlobalSettings"); + } + }; + + private final String signedBy; + private final List<PolicyParser.PrincipalEntry> principals = new ArrayList<>(); + private final String codebase; + + public PolicyIdentifier(final String signedBy, final Collection<PolicyParser.PrincipalEntry> principals, final String codebase) { + if (signedBy != null && signedBy.isEmpty()) { + this.signedBy = null; + } else { + this.signedBy = signedBy; + } + this.principals.addAll(principals); + if (codebase == null) { + this.codebase = ""; + } else { + this.codebase = codebase; + } + } + + public String getSignedBy() { + return signedBy; + } + + public List<PolicyParser.PrincipalEntry> getPrincipals() { + return principals; + } + + public String getCodebase() { + return codebase; + } + + public static boolean isDefaultPolicyIdentifier(final PolicyIdentifier policyIdentifier) { + return policyIdentifier.getSignedBy() == null + && policyIdentifier.getPrincipals().isEmpty() + && policyIdentifier.getCodebase().isEmpty(); + } + + @Override + public String toString() { + final String newline = "<br>"; + final List<String> props = new ArrayList<>(); + if (!codebase.isEmpty()) { + props.add("codebase=" + codebase); + props.add(newline); + } + if (!principals.isEmpty()) { + props.add("principals=" + principals); + props.add(newline); + } + if (signedBy != null && !signedBy.isEmpty()) { + props.add("signedBy=" + signedBy); + props.add(newline); + } + final StringBuilder sb = new StringBuilder(); + sb.append("<html>"); + if (!props.isEmpty()) { + for (final String prop : props.subList(0, props.size() - 1)) { + sb.append(prop); + } + } + sb.append("</html>"); + return sb.toString(); + } + + public String toStringNoHtml() { + return "codebase='" + codebase + '\'' + + " principals=" + principals + + " signedBy='" + signedBy + '\''; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof PolicyIdentifier)) return false; + + final PolicyIdentifier that = (PolicyIdentifier) o; + + if (signedBy != null ? !signedBy.equals(that.signedBy) : that.signedBy != null) return false; + if (!principals.equals(that.principals)) return false; + return codebase.equals(that.codebase); + + } + + @Override + public int hashCode() { + int result = signedBy != null ? signedBy.hashCode() : 0; + result = 31 * result + (principals != null ? principals.hashCode() : 0); + result = 31 * result + (codebase.hashCode()); + return result; + } +}
--- a/netx/net/sourceforge/jnlp/util/docprovider/PolicyEditorTextsProvider.java Wed Jul 29 18:08:16 2015 +0200 +++ b/netx/net/sourceforge/jnlp/util/docprovider/PolicyEditorTextsProvider.java Thu Jul 30 10:57:21 2015 -0400 @@ -68,7 +68,7 @@ public String getSynopsis() { return super.getSynopsis() + getFormatter().wrapParagraph(getFormatter().process(getFormatter().getBoldOpening() + " " + getId() + " " + - getFormatter().getBoldCloseNwlineBoldOpen() + getId() + " [-file] " + getFormatter().getBoldClosing() + Translator.R("PEsynopseP1") + " "+getFormatter().getBold("[-codebase] ") + Translator.R("PEsynopseP2"))); + getFormatter().getBoldCloseNwlineBoldOpen() + getId() + " [-file] " + getFormatter().getBoldClosing() + Translator.R("PEsynopseP1"))); } @Override
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPermissionTest.java Wed Jul 29 18:08:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/*Copyright (C) 2014 Red Hat, Inc. - -This file is part of IcedTea. - -IcedTea is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 2. - -IcedTea is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with IcedTea; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. - */ - -package net.sourceforge.jnlp.security.policyeditor; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class CustomPermissionTest { - - @Test - public void assertFieldsPopulateCorrectly() throws Exception { - final CustomPermission cp = new CustomPermission("type", "target", "some,actions"); - assertTrue("Permission type should be \"type\"", cp.type.equals("type")); - assertTrue("Permission target should be \"target\"", cp.target.equals("target")); - assertTrue("Permission actions should be \"some,actions\"", cp.actions.equals("some,actions")); - } - - @Test - public void testFromStringWithoutActions() throws Exception { - final CustomPermission cp = CustomPermission.fromString("permission java.lang.RuntimePermission \"queuePrintJob\";"); - assertTrue("Permission type should be \"java.lang.RuntimePermission\"", cp.type.equals("java.lang.RuntimePermission")); - assertTrue("Permission target should be \"queuePrintJob\"", cp.target.equals("queuePrintJob")); - assertTrue("Permission actions should be empty", cp.actions.isEmpty()); - } - - @Test - public void testFromStringWithActions() throws Exception { - final CustomPermission cp = CustomPermission.fromString("permission java.io.FilePermission \"*\", \"read,write\";"); - assertTrue("Permission type should be \"java.io.FilePermission\"", cp.type.equals("java.io.FilePermission")); - assertTrue("Permission target should be \"*\"", cp.target.equals("*")); - assertTrue("Permission actions should be \"read,write\"", cp.actions.equals("read,write")); - } - - @Test - public void testMissingQuotationMarks() throws Exception { - final CustomPermission cp = CustomPermission.fromString("permission java.io.FilePermission *, read,write;"); - assertTrue("Custom permission should be null", cp == null); - } - - @Test - public void testActionsMissingComma() throws Exception { - final String missingComma = "permission java.io.FilePermission \"*\" \"read,write\";"; - final CustomPermission cp1 = CustomPermission.fromString(missingComma); - assertTrue("Custom permission for " + missingComma + " should be null", cp1 == null); - } - - @Test - public void testActionsMissingFirstQuote() throws Exception { - final String missingFirstQuote = "permission java.io.FilePermission \"*\", read,write\";"; - final CustomPermission cp2 = CustomPermission.fromString(missingFirstQuote); - assertTrue("Custom permission for " + missingFirstQuote + " should be null", cp2 == null); - } - - @Test - public void testActionsMissingSecondQuote() throws Exception { - final String missingSecondQuote = "permission java.io.FilePermission \"*\", \"read,write;"; - final CustomPermission cp3 = CustomPermission.fromString(missingSecondQuote); - assertTrue("Custom permission for " + missingSecondQuote + " should be null", cp3 == null); - } - - @Test - public void testActionsMissingBothQuotes() throws Exception { - final String missingBothQuotes = "permission java.io.FilePermission \"*\", read,write;"; - final CustomPermission cp4 = CustomPermission.fromString(missingBothQuotes); - assertTrue("Custom permission for " + missingBothQuotes + " should be null", cp4 == null); - } - - @Test - public void testActionsMissingAllPunctuation() throws Exception { - final String missingAll = "permission java.io.FilePermission \"*\" read,write;"; - final CustomPermission cp5 = CustomPermission.fromString(missingAll); - assertTrue("Custom permission for " + missingAll + " should be null", cp5 == null); - } - - @Test - public void testToString() throws Exception { - final CustomPermission cp = new CustomPermission("java.io.FilePermission", "*", "read"); - final String expected = "permission java.io.FilePermission \"*\", \"read\";"; - assertTrue("Permissions string should have equalled " + expected, cp.toString().equals(expected)); - } - - @Test - public void testToStringWithNoActions() throws Exception { - final CustomPermission cp = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); - final String expected = "permission java.lang.RuntimePermission \"createClassLoader\";"; - assertEquals(expected, cp.toString()); - } - - @Test - public void testToStringWithEmptyActions() throws Exception { - final CustomPermission cp = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", ""); - final String expected = "permission java.lang.RuntimePermission \"createClassLoader\";"; - assertEquals(expected, cp.toString()); - } - - @Test - public void testCompareToWithNoActions() throws Exception { - final CustomPermission cp1 = new CustomPermission("java.io.FilePermission", "*", "read"); - final CustomPermission cp2 = new CustomPermission("java.io.FilePermission", "${user.home}${/}*", "read"); - final CustomPermission cp3 = new CustomPermission("java.lang.RuntimePermission", "queuePrintJob"); - assertTrue("cp1.compareTo(cp2) should be > 0", cp1.compareTo(cp2) > 0); - assertTrue("cp1.compareTo(cp1) should be 0", cp1.compareTo(cp1) == 0); - assertTrue("cp2.compareTo(cp3) should be < 0", cp2.compareTo(cp3) < 0); - } - - @Test - public void testCompareToWithEmptyActions() throws Exception { - final CustomPermission cp1 = new CustomPermission("java.io.FilePermission", "*", "read"); - final CustomPermission cp2 = new CustomPermission("java.io.FilePermission", "${user.home}${/}*", "read"); - final CustomPermission cp3 = new CustomPermission("java.lang.RuntimePermission", "queuePrintJob", ""); - assertTrue("cp1.compareTo(cp2) should be > 0", cp1.compareTo(cp2) > 0); - assertTrue("cp1.compareTo(cp1) should be 0", cp1.compareTo(cp1) == 0); - assertTrue("cp2.compareTo(cp3) should be < 0", cp2.compareTo(cp3) < 0); - } - - @Test - public void testConstructFromEnumsToString() throws Exception { - final CustomPermission cp = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.READ); - final String permissionString = "permission java.io.FilePermission \"${user.home}\", \"read\";"; - assertEquals(permissionString, cp.toString()); - } - - @Test - public void testEquals() throws Exception { - final CustomPermission cp1 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER); - final CustomPermission cp2 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER); - final CustomPermission cp3 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.ACCESS_THREADS); - assertEquals(cp1, cp2); - assertNotEquals(cp1, cp3); - } - - @Test - public void testHashcode() throws Exception { - final CustomPermission cp1 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER); - final CustomPermission cp2 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER); - final CustomPermission cp3 = new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.ACCESS_THREADS); - assertEquals(cp1.hashCode(), cp2.hashCode()); - assertNotEquals(cp1.hashCode(), cp3.hashCode()); - } -}
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewerTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/CustomPolicyViewerTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,35 +36,33 @@ package net.sourceforge.jnlp.security.policyeditor; +import static net.sourceforge.jnlp.security.policyeditor.PolicyEditor.identifierFromCodebase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.Collection; - -import net.sourceforge.jnlp.security.policyeditor.CustomPermission; -import net.sourceforge.jnlp.security.policyeditor.CustomPolicyViewer; -import net.sourceforge.jnlp.security.policyeditor.PolicyEditor; - import org.junit.Before; import org.junit.Test; +import sun.security.provider.PolicyParser; + +import java.util.Collection; public class CustomPolicyViewerTest { private CustomPolicyViewer viewer; - private static final String CODEBASE = "http://example.com"; - private static final CustomPermission PERMISSION = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); + private static final PolicyIdentifier IDENTIFIER = identifierFromCodebase("http://example.com"); + private static final CustomPolicyViewer.DisplayablePermission PERMISSION = CustomPolicyViewer.DisplayablePermission.from(new PolicyParser.PermissionEntry("java.lang.RuntimePermission", "createClassLoader", null)); @Before public void setupViewer() { - viewer = new CustomPolicyViewer(new PolicyEditor(null), CODEBASE); + viewer = new CustomPolicyViewer(new PolicyEditor(null), IDENTIFIER); } @Test(expected = NullPointerException.class) public void testConstructorWithNullPolicyEditor() throws Exception { - new CustomPolicyViewer(null, CODEBASE); + new CustomPolicyViewer(null, IDENTIFIER); } @Test(expected = NullPointerException.class) @@ -121,7 +119,7 @@ @Test public void testGetCopyOfCustomPermissionsReturnsCopy() throws Exception { - final Collection<CustomPermission> permissions = viewer.getCopyOfCustomPermissions(); + final Collection<CustomPolicyViewer.DisplayablePermission> permissions = viewer.getCopyOfCustomPermissions(); permissions.add(PERMISSION); assertNotEquals("Sets should be distinct", viewer.getCopyOfCustomPermissions(), permissions); assertNotEquals("Sizes should not match", viewer.getCopyOfCustomPermissions().size(), permissions.size());
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorControllerTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorControllerTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -39,12 +39,14 @@ import net.sourceforge.jnlp.util.FileUtils; import org.junit.Before; import org.junit.Test; +import sun.security.provider.PolicyParser; import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -53,6 +55,23 @@ public class PolicyEditorControllerTest { + private static final String SIGNED_BY = "someCA"; + private static final String CODEBASE = "http://example.com"; + private static final List<PolicyParser.PrincipalEntry> EMPTY_PRINCIPALS = Collections.emptyList(); + private static final PolicyIdentifier DEFAULT_IDENTIFIER = new PolicyIdentifier(SIGNED_BY, EMPTY_PRINCIPALS, CODEBASE); + private static final String LINEBREAK = System.getProperty("line.separator"); + + private static final String EXAMPLE_POLICY_1 = "grant {" + LINEBREAK + + "permission some.java.permission \"somePermission\";" + LINEBREAK + + "};" + LINEBREAK; + private static final String EXAMPLE_POLICY_2 = "grant {" + LINEBREAK + + "permission some.other.java.permission \"somePermission\";" + LINEBREAK + + "};" + LINEBREAK; + + private static final String CLIPBOARD_POLICY = "grant codeBase \"http://example.com\" {" + LINEBREAK + + "permission java.awt.AWTPermission \"accessClipboard\";" + LINEBREAK + + "};" + LINEBREAK; + private String tempFilePath; private PolicyEditorController controller; @@ -65,8 +84,7 @@ @Test public void testChangesMadeInitiallyFalse() throws Exception { - // #setFile() counts as a change made - assertTrue("Controller should report changes made initially", controller.changesMade()); + assertFalse("Controller should report changes made initially", controller.changesMade()); } @Test @@ -83,150 +101,145 @@ @Test public void testFileHasChangedWithChange() throws Exception { assertFalse("Controller should report file has changed initially", controller.fileHasChanged()); - final String codebase = "http://example.com"; - final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD; - final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - FileUtils.saveFile(policyEntry.toString(), new File(tempFilePath)); + FileUtils.saveFile(EXAMPLE_POLICY_1, new File(tempFilePath)); controller.openAndParsePolicyFile(); - final Collection<PolicyEditorPermissions> editorPermissions2 = Collections.singleton(PolicyEditorPermissions.ALL_AWT); - final PolicyEntry policyEntry2 = new PolicyEntry(codebase, editorPermissions2, customPermissions); - FileUtils.saveFile(policyEntry2.toString(), new File(tempFilePath)); + FileUtils.saveFile(EXAMPLE_POLICY_2, new File(tempFilePath)); assertTrue("File should be marked changed after being externally modified", controller.fileHasChanged()); } @Test - public void testInitialCodebase() throws Exception { - final Collection<String> initialCodebases = controller.getCodebases(); - assertEquals("Controller should have no codebases to begin with", 0, initialCodebases.size()); + public void testInitialIdentifier() throws Exception { + final Collection<PolicyIdentifier> initialIdentifiers = controller.getIdentifiers(); + assertEquals("Controller should have no identifiers to begin with", 0, initialIdentifiers.size()); } @Test - public void testAddCodebase() throws Exception { - final String urlString = "http://example.com"; - controller.addCodebase(urlString); - final Collection<String> codebases = controller.getCodebases(); - assertTrue("Controller should have http://example.com", codebases.contains(urlString)); - assertEquals("Controller should only have two codebases", 1, codebases.size()); + public void testAddIdentifier() throws Exception { + controller.addIdentifier(DEFAULT_IDENTIFIER); + final Collection<PolicyIdentifier> identifiers = controller.getIdentifiers(); + assertTrue("Controller should have " + DEFAULT_IDENTIFIER, identifiers.contains(DEFAULT_IDENTIFIER)); + assertEquals("Controller should only have two identifiers", 1, identifiers.size()); } @Test - public void testAddMultipleCodebases() throws Exception { - final Set<String> toAdd = new HashSet<String>(); - toAdd.add("http://example.com"); - toAdd.add("http://icedtea.classpath.org"); - for (final String cb : toAdd) { - controller.addCodebase(cb); + public void testAddMultipleIdentifiers() throws Exception { + final Set<PolicyIdentifier> toAdd = new HashSet<>(); + toAdd.add(DEFAULT_IDENTIFIER); + final PolicyIdentifier newIdentifier = new PolicyIdentifier(null, EMPTY_PRINCIPALS, "http://icedtea.classpath.org"); + toAdd.add(newIdentifier); + for (final PolicyIdentifier id : toAdd) { + controller.addIdentifier(id); } - final Collection<String> codebases = controller.getCodebases(); - for (final String codebase : toAdd) { - assertTrue("Controller should have " + codebase, codebases.contains(codebase)); + final Collection<PolicyIdentifier> identifiers = controller.getIdentifiers(); + for (final PolicyIdentifier id : toAdd) { + assertTrue("Controller should have " + id, identifiers.contains(id)); } } @Test - public void testRemoveCodebase() throws Exception { - final String urlString = "http://example.com"; - controller.addCodebase(urlString); - final Collection<String> codebases = controller.getCodebases(); - assertTrue("Controller should have http://example.com", codebases.contains(urlString)); - assertEquals("Controller should only have one codebase", 1, codebases.size()); - controller.removeCodebase(urlString); - final Collection<String> afterRemove = controller.getCodebases(); - assertFalse("Controller should not have http://example.com. Contained: " + afterRemove, afterRemove.contains(urlString)); - assertEquals("Controller should have no codebases", 0, afterRemove.size()); + public void testRemoveIdentifier() throws Exception { + controller.addIdentifier(DEFAULT_IDENTIFIER); + final Collection<PolicyIdentifier> identifiers = controller.getIdentifiers(); + assertTrue("Controller should have " + DEFAULT_IDENTIFIER, identifiers.contains(DEFAULT_IDENTIFIER)); + assertEquals("Controller should only have one identifier", 1, identifiers.size()); + controller.removeIdentifier(DEFAULT_IDENTIFIER); + final Collection<PolicyIdentifier> afterRemove = controller.getIdentifiers(); + assertFalse("Controller should not have " + DEFAULT_IDENTIFIER + ". Contained: " + afterRemove, afterRemove.contains(DEFAULT_IDENTIFIER)); + assertEquals("Controller should have no identifiers", Collections.<PolicyIdentifier>emptySet(), afterRemove); } @Test - public void testCopyPasteCodebase() throws Exception { - final String copyUrl = "http://example.com"; + public void testCopyPasteIdentifiers() throws Exception { final String pasteUrl = "http://example.com/example"; + final PolicyIdentifier pasteIdentifier = new PolicyIdentifier(null, EMPTY_PRINCIPALS, pasteUrl); final PolicyEditorPermissions clipBoard = PolicyEditorPermissions.CLIPBOARD; - controller.addCodebase(copyUrl); - controller.setPermission(copyUrl, clipBoard, Boolean.TRUE); - final Collection<String> beforePasteCodebases = controller.getCodebases(); - assertTrue("Controller should contain original codebase: " + copyUrl, beforePasteCodebases.contains(copyUrl)); - assertTrue(copyUrl + " should have " + clipBoard, controller.getPermissions(copyUrl).get(clipBoard)); - controller.copyCodebaseToClipboard(copyUrl); + controller.addIdentifier(DEFAULT_IDENTIFIER); + controller.setPermission(DEFAULT_IDENTIFIER, clipBoard, Boolean.TRUE); + final Collection<PolicyIdentifier> beforePasteIdentifiers = controller.getIdentifiers(); + assertTrue("Controller should contain original identifier: " + DEFAULT_IDENTIFIER, beforePasteIdentifiers.contains(DEFAULT_IDENTIFIER)); + assertTrue(DEFAULT_IDENTIFIER + " should have " + clipBoard, controller.getPermissions(DEFAULT_IDENTIFIER).get(clipBoard)); + controller.copyPolicyEntryToClipboard(DEFAULT_IDENTIFIER); final PolicyEntry clipboardEntry = PolicyEditorController.getPolicyEntryFromClipboard(); - controller.addPolicyEntry(new PolicyEntry(pasteUrl, clipboardEntry.getPermissions(), clipboardEntry.getCustomPermissions())); - final Collection<String> afterPasteCodebases = controller.getCodebases(); - assertTrue("Controller should still contain original codebase: " + copyUrl, afterPasteCodebases.contains(copyUrl)); - assertTrue("Controller should also contain pasted codebase:" + pasteUrl, afterPasteCodebases.contains(pasteUrl)); - assertTrue(copyUrl + " should have " + clipBoard, controller.getPermissions(copyUrl).get(clipBoard)); - assertTrue(pasteUrl + " should have " + clipBoard, controller.getPermissions(pasteUrl).get(clipBoard)); + final PolicyEntry newEntry = new PolicyEntry.Builder() + .codebase(pasteUrl) + .permissions(clipboardEntry.getPermissions()) + .customPermissions(clipboardEntry.getCustomPermissions()) + .build(); + controller.addPolicyEntry(newEntry); + final Collection<PolicyIdentifier> afterPasteIdentifiers = controller.getIdentifiers(); + assertTrue("Controller should still contain original identifier: " + DEFAULT_IDENTIFIER, afterPasteIdentifiers.contains(DEFAULT_IDENTIFIER)); + assertTrue("Controller should also contain pasted identifier:" + pasteIdentifier, afterPasteIdentifiers.contains(pasteIdentifier)); + assertTrue(DEFAULT_IDENTIFIER + " should have " + clipBoard, controller.getPermissions(DEFAULT_IDENTIFIER).get(clipBoard)); + assertTrue(pasteIdentifier + " should have " + clipBoard, controller.getPermissions(pasteIdentifier).get(clipBoard)); } @Test public void testAddPolicyEntry() throws Exception { - final String codebase = "http://example.com"; final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD; final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); + final Collection<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(customPermission); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .identifier(DEFAULT_IDENTIFIER) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); controller.addPolicyEntry(policyEntry); - final Collection<String> codebases = controller.getCodebases(); - assertTrue("Controller should have " + codebase, codebases.contains(codebase)); - assertEquals("Controller should only have one codebase", 1, codebases.size()); - assertTrue("Controller should have granted " + editorPermissions, controller.getPermission(codebase, editorPermissions)); - assertTrue("Controller should have granted " + customPermission, controller.getCustomPermissions(codebase).contains(customPermission)); + final Collection<PolicyIdentifier> identifiers = controller.getIdentifiers(); + assertTrue("Controller should have " + DEFAULT_IDENTIFIER, identifiers.contains(DEFAULT_IDENTIFIER)); + assertEquals("Controller should only have one identifier", 1, identifiers.size()); + assertTrue("Controller should have granted " + editorPermissions, controller.getPermission(DEFAULT_IDENTIFIER, editorPermissions)); + assertTrue("Controller should have granted " + customPermission, controller.getCustomPermissions(DEFAULT_IDENTIFIER).contains(customPermission)); } @Test public void testAddCustomPermissionNoActions() throws Exception { - final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); - controller.addCustomPermission(codebase, customPermission); - assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission)); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader"); + controller.addCustomPermission(DEFAULT_IDENTIFIER, customPermission); + assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(DEFAULT_IDENTIFIER).contains(customPermission)); } @Test public void testAddCustomPermissionEmptyActions() throws Exception { - final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", ""); - controller.addCustomPermission(codebase, customPermission); - assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission)); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader", ""); + controller.addCustomPermission(DEFAULT_IDENTIFIER, customPermission); + assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(DEFAULT_IDENTIFIER).contains(customPermission)); } @Test public void testClearCustomPermissionsNoActions() throws Exception { - final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); - controller.addCustomPermission(codebase, customPermission); - assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission)); - controller.clearCustomCodebase(codebase); - assertEquals(0, controller.getCustomPermissions(codebase).size()); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader"); + controller.addCustomPermission(DEFAULT_IDENTIFIER, customPermission); + assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(DEFAULT_IDENTIFIER).contains(customPermission)); + controller.clearCustomIdentifier(DEFAULT_IDENTIFIER); + assertEquals(0, controller.getCustomPermissions(DEFAULT_IDENTIFIER).size()); } @Test public void testClearCustomPermissionsEmptyActions() throws Exception { - final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", ""); - controller.addCustomPermission(codebase, customPermission); - assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission)); - controller.clearCustomCodebase(codebase); - assertEquals(0, controller.getCustomPermissions(codebase).size()); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader", ""); + controller.addCustomPermission(DEFAULT_IDENTIFIER, customPermission); + assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(DEFAULT_IDENTIFIER).contains(customPermission)); + controller.clearCustomIdentifier(DEFAULT_IDENTIFIER); + assertEquals(0, controller.getCustomPermissions(DEFAULT_IDENTIFIER).size()); } @Test - public void testReturnedCodebasesIsCopy() throws Exception { - final Collection<String> original = controller.getCodebases(); - original.add("some invalid value"); - original.remove(""); - final Collection<String> second = controller.getCodebases(); - assertEquals("Controller should have no codebases", 0, second.size()); + public void testReturnedIdentifiersIsCopy() throws Exception { + final Collection<PolicyIdentifier> original = controller.getIdentifiers(); + original.add(new PolicyIdentifier("invalidSigner", EMPTY_PRINCIPALS, "invalidURL")); + original.remove(DEFAULT_IDENTIFIER); + final Collection<PolicyIdentifier> second = controller.getIdentifiers(); + assertEquals("Controller should have no identifiers", 0, second.size()); } @Test public void testReturnedPermissionsMapIsCopy() throws Exception { - final Map<PolicyEditorPermissions, Boolean> original = controller.getPermissions(""); + final Map<PolicyEditorPermissions, Boolean> original = controller.getPermissions(DEFAULT_IDENTIFIER); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { original.put(perm, true); } - final Map<PolicyEditorPermissions, Boolean> second = controller.getPermissions(""); + final Map<PolicyEditorPermissions, Boolean> second = controller.getPermissions(DEFAULT_IDENTIFIER); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : second.entrySet()) { assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue()); } @@ -234,18 +247,18 @@ @Test public void testReturnedCustomPermissionsSetIsCopy() throws Exception { - final Collection<CustomPermission> original = controller.getCustomPermissions(""); + final Collection<PolicyParser.PermissionEntry> original = controller.getCustomPermissions(DEFAULT_IDENTIFIER); assertTrue("There should not be any custom permissions to start", original.isEmpty()); - original.add(new CustomPermission("java.io.FilePermission", "*", "write")); - final Collection<CustomPermission> second = controller.getCustomPermissions(""); + original.add(new CustomPolicyViewer.DisplayablePermission("java.io.FilePermission", "*", "write")); + final Collection<PolicyParser.PermissionEntry> second = controller.getCustomPermissions(DEFAULT_IDENTIFIER); assertTrue("The custom permission should not have been present", second.isEmpty()); } @Test public void testDefaultPermissionsAllFalse() throws Exception { - final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions(""); - controller.addCodebase("http://example.com"); - final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions("http://example.com"); + final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions(DEFAULT_IDENTIFIER); + controller.addIdentifier(DEFAULT_IDENTIFIER); + final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions(DEFAULT_IDENTIFIER); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : defaultMap.entrySet()) { assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue()); } @@ -256,87 +269,69 @@ @Test public void testAllPermissionsRepresented() throws Exception { - final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions(""); - controller.addCodebase("http://example.com"); - final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions("http://example.com"); - assertTrue("Default codebase permissions keyset should be the same size as enum values set", + final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions(DEFAULT_IDENTIFIER); + controller.addIdentifier(DEFAULT_IDENTIFIER); + final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions(DEFAULT_IDENTIFIER); + assertTrue("Default identifier permissions keyset should be the same size as enum values set", defaultMap.keySet().size() == PolicyEditorPermissions.values().length); - assertTrue("Added codebase permissions keyset should be the same size as enum values set", + assertTrue("Added identifier permissions keyset should be the same size as enum values set", addedMap.keySet().size() == PolicyEditorPermissions.values().length); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { - assertTrue("Permission " + perm + " should be in the editor's codebase keyset", defaultMap.keySet().contains(perm)); + assertTrue("Permission " + perm + " should be in the editor's identifier keyset", defaultMap.keySet().contains(perm)); } for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { - assertTrue("Permission " + perm + " should be in the editor's codebase keyset", addedMap.keySet().contains(perm)); + assertTrue("Permission " + perm + " should be in the editor's identifier keyset", addedMap.keySet().contains(perm)); } } @Test public void testSetGetPermission() throws Exception { - final String codebase = "http://example.com"; - controller.addCodebase(codebase); + controller.addIdentifier(DEFAULT_IDENTIFIER); final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD; - assertFalse("Clipboard permission should not be initially granted", controller.getPermission(codebase, permission)); - controller.setPermission(codebase, permission, true); - assertTrue("Clipboard permission should be granted after being set", controller.getPermission(codebase, permission)); + assertFalse("Clipboard permission should not be initially granted", controller.getPermission(DEFAULT_IDENTIFIER, permission)); + controller.setPermission(DEFAULT_IDENTIFIER, permission, true); + assertTrue("Clipboard permission should be granted after being set", controller.getPermission(DEFAULT_IDENTIFIER, permission)); } @Test public void testClearPermission() throws Exception { - final String codebase = "http://example.com"; - controller.addCodebase(codebase); + controller.addIdentifier(DEFAULT_IDENTIFIER); final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD; - assertFalse("Clipboard permission should not be initially granted", controller.getPermission(codebase, permission)); - controller.setPermission(codebase, permission, true); - assertTrue("Clipboard permission should be granted after being set", controller.getPermission(codebase, permission)); + assertFalse("Clipboard permission should not be initially granted", controller.getPermission(DEFAULT_IDENTIFIER, permission)); + controller.setPermission(DEFAULT_IDENTIFIER, permission, true); + assertTrue("Clipboard permission should be granted after being set", controller.getPermission(DEFAULT_IDENTIFIER, permission)); controller.clearPermissions(); - for (final String cb : controller.getCodebases()) { - for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : controller.getPermissions(cb).entrySet()) { - assertFalse("Permission " + entry.getKey() + " should be false for codebase " + cb, entry.getValue()); + for (final PolicyIdentifier id : controller.getIdentifiers()) { + for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : controller.getPermissions(id).entrySet()) { + assertFalse("Permission " + entry.getKey() + " should be false for identifier " + id, entry.getValue()); } } - assertEquals(0, controller.getCodebases().size()); + assertEquals(0, controller.getIdentifiers().size()); } @Test - public void testCodebaseTrailingSlashesDoNotMatch() throws Exception { - final Collection<String> toAdd = Arrays.asList("http://redhat.com", "http://redhat.com/"); - for (final String cb : toAdd) { - controller.addCodebase(cb); + public void testIdentifierCodebaseTrailingSlashesDoNotMatch() throws Exception { + final PolicyIdentifier firstId = new PolicyIdentifier(SIGNED_BY, EMPTY_PRINCIPALS, "http://example.com"); + final PolicyIdentifier secondId = new PolicyIdentifier(SIGNED_BY, EMPTY_PRINCIPALS, "http://example.com"); + final Collection<PolicyIdentifier> toAdd = Arrays.asList(firstId, secondId); + for (final PolicyIdentifier id : toAdd) { + controller.addIdentifier(id); } - final Collection<String> codebases = controller.getCodebases(); - for (final String codebase : toAdd) { - assertTrue("Controller should have " + codebase, codebases.contains(codebase)); + final Collection<PolicyIdentifier> identifiers = controller.getIdentifiers(); + for (final PolicyIdentifier id : toAdd) { + assertTrue("Controller should have " + id, identifiers.contains(id)); } } @Test public void testOpenAndParsePolicyFile() throws Exception { - final String codebase = "http://example.com"; - final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD; - final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions); - final CustomPermission customPermission = new CustomPermission("com.example.CustomPermission", PermissionTarget.USER_HOME.target, PermissionActions.FILE_ALL.rawString()); - final Collection<CustomPermission> customPermissions = new HashSet<>(Collections.singleton(customPermission)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - FileUtils.saveFile(policyEntry.toString(), new File(tempFilePath)); + final PolicyIdentifier exampleIdentifier = new PolicyIdentifier(null, Collections.<PolicyParser.PrincipalEntry>emptyList(), "http://example.com"); + FileUtils.saveFile(CLIPBOARD_POLICY, new File(tempFilePath)); controller.openAndParsePolicyFile(); - assertEquals("Controller should have one codebase", 1, controller.getCodebases().size()); - assertTrue("Controller should have codebase " + codebase, controller.getCodebases().contains(codebase)); - assertTrue("Controller should grant " + editorPermissions, controller.getPermission(codebase, editorPermissions)); - assertEquals("Custom permission sets were not equal", customPermissions, controller.getCustomPermissions(codebase)); + assertEquals("Controller should have one identifier", 1, controller.getIdentifiers().size()); + assertTrue("Controller should have identifier " + exampleIdentifier, controller.getIdentifiers().contains(exampleIdentifier)); + assertTrue("Controller should grant " + PolicyEditorPermissions.CLIPBOARD + " got: " + controller.getPermissions(exampleIdentifier) + " and: " + controller.getCustomPermissions(exampleIdentifier), controller.getPermission(exampleIdentifier, PolicyEditorPermissions.CLIPBOARD)); + assertEquals("Custom permission set should have been empty", Collections.<PolicyParser.PermissionEntry>emptySet(), controller.getCustomPermissions(exampleIdentifier)); } - @Test - public void testSavePolicyFile() throws Exception { - final String codebase = "http://example.com"; - final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD; - final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - controller.addPolicyEntry(policyEntry); - controller.savePolicyFile(); - final String fileContent = FileUtils.loadFileAsString(new File(tempFilePath)); - assertTrue("Saved file should contain policy entry as string", fileContent.contains(policyEntry.toString())); - } }
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,17 +36,24 @@ package net.sourceforge.jnlp.security.policyeditor; import java.io.File; +import java.util.Collection; +import java.util.Collections; import java.util.Map; -import net.sourceforge.jnlp.annotations.KnownToFail; import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; +import sun.security.provider.PolicyParser; public class PolicyEditorParsingTest { + private static final Collection<PolicyParser.PrincipalEntry> EMPTY_PRINCIPALS = Collections.emptyList(); + private static final String EXAMPLE_CODEBASE = "http://example.com"; + private static final PolicyIdentifier DEFAULT_IDENTIFIER = new PolicyIdentifier(null, EMPTY_PRINCIPALS, null); + private static final PolicyIdentifier EXAMPLE_IDENTIFIER = new PolicyIdentifier(null, EMPTY_PRINCIPALS, EXAMPLE_CODEBASE); + private File file; private PolicyFileModel policyFileModel = new PolicyFileModel(); private Map<PolicyEditorPermissions, Boolean> permissions; @@ -110,18 +117,18 @@ file.deleteOnExit(); } - private void setupTest(final String policyContents, final String codebase) throws Exception { + private void setupTest(final String policyContents, final PolicyIdentifier identifier) throws Exception { FileUtils.saveFile(policyContents, file); policyFileModel = new PolicyFileModel(file.getCanonicalFile()); policyFileModel.openAndParsePolicyFile(); - policyFileModel.addCodebase(""); - policyFileModel.addCodebase(codebase); - permissions = policyFileModel.getCopyOfPermissions().get(codebase); + policyFileModel.addIdentifier(DEFAULT_IDENTIFIER); + policyFileModel.addIdentifier(identifier); + permissions = policyFileModel.getCopyOfPermissions().get(identifier); } @Test public void testNormalPolicy() throws Exception { - setupTest(NORMAL_POLICY, ""); + setupTest(NORMAL_POLICY, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) { @@ -133,7 +140,7 @@ @Test public void testNormalPolicyWithCRLFEndings() throws Exception { // This is the same test as testNormalPolicy on systems where the line separator is \r\n - setupTest(NORMAL_POLICY_CRLF, ""); + setupTest(NORMAL_POLICY_CRLF, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) { @@ -145,7 +152,7 @@ @Test public void testNormalPolicyWithLFEndings() throws Exception { // This is the same test as testNormalPolicy on systems where the line separator is \n - setupTest(NORMAL_POLICY_LF, ""); + setupTest(NORMAL_POLICY_LF, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) { @@ -157,7 +164,7 @@ @Test public void testNormalPolicyWithMixedEndings() throws Exception { // This is the same test as testNormalPolicy on systems where the line separator is \n - setupTest(NORMAL_POLICY_MIXED_ENDINGS, ""); + setupTest(NORMAL_POLICY_MIXED_ENDINGS, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) { @@ -168,7 +175,7 @@ @Test public void testCommentHeaders() throws Exception { - setupTest(COMMENT_HEADER, ""); + setupTest(COMMENT_HEADER, DEFAULT_IDENTIFIER); for (final PolicyEditorPermissions perm : permissions.keySet()) { assertFalse("Permission " + perm + " should not be granted", permissions.get(perm)); } @@ -176,7 +183,7 @@ @Test public void testCommentBlockedPermission() throws Exception { - setupTest(COMMENT_BLOCKED_PERMISSION, ""); + setupTest(COMMENT_BLOCKED_PERMISSION, DEFAULT_IDENTIFIER); for (final PolicyEditorPermissions perm : permissions.keySet()) { assertFalse("Permission " + perm + " should not be granted", permissions.get(perm)); } @@ -184,7 +191,7 @@ @Test public void testCommentBlockedPolicy() throws Exception { - setupTest(COMMENT_BLOCKED_POLICY, ""); + setupTest(COMMENT_BLOCKED_POLICY, DEFAULT_IDENTIFIER); for (final PolicyEditorPermissions perm : permissions.keySet()) { assertFalse("Permission " + perm + " should not be granted", permissions.get(perm)); } @@ -192,7 +199,7 @@ @Test public void testCommentedLine() throws Exception { - setupTest(COMMENTED_PERMISSION, ""); + setupTest(COMMENTED_PERMISSION, DEFAULT_IDENTIFIER); for (final PolicyEditorPermissions perm : permissions.keySet()) { assertFalse("Permission " + perm + " should not be granted", permissions.get(perm)); } @@ -200,7 +207,7 @@ @Test public void testMultiplePermissions() throws Exception { - setupTest(MULTIPLE_PERMISSION_POLICY, ""); + setupTest(MULTIPLE_PERMISSION_POLICY, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); assertTrue("Permissions should include WRITE_LOCAL_FILES", permissions.get(PolicyEditorPermissions.WRITE_LOCAL_FILES)); @@ -211,10 +218,9 @@ } } - @KnownToFail @Test public void testMultiplePermissionsPerLine() throws Exception { - setupTest(MULTIPLE_PERMISSIONS_PER_LINE, ""); + setupTest(MULTIPLE_PERMISSIONS_PER_LINE, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); assertTrue("Permissions should include WRITE_LOCAL_FILES", permissions.get(PolicyEditorPermissions.WRITE_LOCAL_FILES)); @@ -225,10 +231,9 @@ } } - @KnownToFail @Test public void testMissingWhitespace() throws Exception { - setupTest(MISSING_WHITESPACE_POLICY, ""); + setupTest(MISSING_WHITESPACE_POLICY, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { @@ -240,7 +245,7 @@ @Test public void testPolicyWithCodebase() throws Exception { - setupTest(CODEBASE_POLICY, "http://example.com"); + setupTest(CODEBASE_POLICY, EXAMPLE_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { @@ -254,7 +259,7 @@ public void testCodebaseTrailingSlashesDoNotMatch() throws Exception { // note the trailing '/' - looks like the same URL but is not. JDK PolicyTool considers these as // different codeBases, so so does PolicyEditor - setupTest(CODEBASE_POLICY, "http://example.com/"); + setupTest(CODEBASE_POLICY, EXAMPLE_IDENTIFIER); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) { @@ -265,7 +270,7 @@ @Test public void testCommentAfterPermission() throws Exception { - setupTest(COMMENT_AFTER_PERMISSION, ""); + setupTest(COMMENT_AFTER_PERMISSION, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { @@ -277,7 +282,7 @@ @Test public void testNormalPolicyWithHeader() throws Exception { - setupTest(NORMAL_POLICY_WITH_HEADER, ""); + setupTest(NORMAL_POLICY_WITH_HEADER, DEFAULT_IDENTIFIER); assertTrue("Permissions should include READ_LOCAL_FILES", permissions.get(PolicyEditorPermissions.READ_LOCAL_FILES)); for (final PolicyEditorPermissions perm : permissions.keySet()) { if (!perm.equals(PolicyEditorPermissions.READ_LOCAL_FILES)) {
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissionsTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissionsTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,10 +36,9 @@ package net.sourceforge.jnlp.security.policyeditor; -import java.util.regex.Pattern; +import org.junit.Test; + import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import org.junit.Test; public class PolicyEditorPermissionsTest { @@ -65,39 +64,4 @@ } } - @Test - public void testActionsRegex() throws Exception { - final Pattern pattern = CustomPermission.ACTIONS_PERMISSION; - - final String actionsPermission = "permission java.io.FilePermission \"${user.home}\", \"read\";"; - final String targetPermission = "permission java.io.RuntimePermission \"queuePrintJob\";"; - final String badPermission = "permission java.io.FilePermission user.home read;"; - - assertTrue(actionsPermission + " should match", pattern.matcher(actionsPermission).matches()); - assertFalse(targetPermission + " should not match", pattern.matcher(targetPermission).matches()); - assertFalse(badPermission + " should not match", pattern.matcher(badPermission).matches()); - } - - @Test - public void testTargetRegex() throws Exception { - final Pattern pattern = CustomPermission.TARGET_PERMISSION; - - final String actionsPermission = "permission java.io.FilePermission \"${user.home}\", \"read\";"; - final String targetPermission = "permission java.io.RuntimePermission \"queuePrintJob\";"; - final String badPermission = "permission java.io.FilePermission user.home read;"; - - assertFalse(actionsPermission + " should not match", pattern.matcher(actionsPermission).matches()); - assertTrue(targetPermission + " should match", pattern.matcher(targetPermission).matches()); - assertFalse(badPermission + " should not match", pattern.matcher(badPermission).matches()); - } - - @Test - public void testRegexesAgainstBadPermissionNames() throws Exception { - final Pattern targetPattern = CustomPermission.TARGET_PERMISSION; - final Pattern actionsPattern = CustomPermission.ACTIONS_PERMISSION; - final String badPermission = "permission abc123^$% \"target\", \"actions\""; - - assertFalse(badPermission + " should not match", targetPattern.matcher(badPermission).matches()); - assertFalse(badPermission + " should not match", actionsPattern.matcher(badPermission).matches()); - } }
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -36,6 +36,7 @@ package net.sourceforge.jnlp.security.policyeditor; +import static net.sourceforge.jnlp.security.policyeditor.PolicyEditor.identifierFromCodebase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -48,6 +49,7 @@ import org.junit.Before; import org.junit.Test; +import sun.security.provider.PolicyParser; public class PolicyEditorTest { @@ -58,6 +60,7 @@ public void setNewTempfile() throws Exception { tempFilePath = File.createTempFile("policyeditor", null).getCanonicalPath(); editor = new PolicyEditor(tempFilePath); + editor.openPolicyFileSynchronously(); } @Test @@ -65,13 +68,14 @@ final Collection<String> initialCodebases = editor.getCodebases(); assertTrue("Editor should have one codebase to begin with", initialCodebases.size() == 1); assertTrue("Editor's initial codebase should be \"\" (empty string)", - initialCodebases.toArray(new String[0])[0].equals("")); + initialCodebases.toArray(new String[initialCodebases.size()])[0].equals("")); } @Test public void testAddCodebase() throws Exception { final String urlString = "http://example.com"; - editor.addNewCodebase(urlString); + final PolicyIdentifier identifier = identifierFromCodebase(urlString); + editor.addNewEntry(identifier); final Collection<String> codebases = editor.getCodebases(); assertTrue("Editor should have default codebase", codebases.contains("")); assertTrue("Editor should have http://example.com", codebases.contains(urlString)); @@ -80,11 +84,11 @@ @Test public void addMultipleCodebases() throws Exception { - final Set<String> toAdd = new HashSet<String>(); + final Set<String> toAdd = new HashSet<>(); toAdd.add("http://example.com"); toAdd.add("http://icedtea.classpath.org"); for (final String cb : toAdd) { - editor.addNewCodebase(cb); + editor.addNewEntry(identifierFromCodebase(cb)); } final Collection<String> codebases = editor.getCodebases(); assertTrue("Editor should have default codebase", codebases.contains("")); @@ -96,7 +100,7 @@ @Test public void testAddInvalidUrlCodebase() throws Exception { final String invalidUrl = "url.com"; // missing protocol -> invalid - editor.addNewCodebase(invalidUrl); + editor.addNewEntry(identifierFromCodebase(invalidUrl)); final Collection<String> codebases = editor.getCodebases(); assertTrue("Editor should have default codebase", codebases.contains("")); assertTrue("Editor should only have default codebase", codebases.size() == 1); @@ -105,12 +109,13 @@ @Test public void testRemoveCodebase() throws Exception { final String urlString = "http://example.com"; - editor.addNewCodebase(urlString); + final PolicyIdentifier identifier = identifierFromCodebase(urlString); + editor.addNewEntry(identifier); final Collection<String> codebases = editor.getCodebases(); assertTrue("Editor should have default codebase", codebases.contains("")); assertTrue("Editor should have http://example.com", codebases.contains(urlString)); assertEquals("Editor should only have two codebases", codebases.size(), 2); - editor.removeCodebase(urlString); + editor.removeIdentifier(identifier); final Collection<String> afterRemove = editor.getCodebases(); assertTrue("Editor should have default codebase", afterRemove.contains("")); assertFalse("Editor should not have http://example.com. Contained: " + afterRemove, afterRemove.contains(urlString)); @@ -122,16 +127,18 @@ final String originalUrl = "http://example.com"; final String renamedUrl = "http://example.com/example"; final PolicyEditorPermissions clipBoard = PolicyEditorPermissions.CLIPBOARD; - editor.addNewCodebase(originalUrl); - editor.setPermission(originalUrl, clipBoard, Boolean.TRUE); + final PolicyIdentifier identifier = identifierFromCodebase(originalUrl); + editor.addNewEntry(identifier); + editor.setPermission(identifier, clipBoard, Boolean.TRUE); final Collection<String> beforeRenameCodebases = editor.getCodebases(); assertTrue("Editor should contain " + originalUrl, beforeRenameCodebases.contains(originalUrl)); - assertTrue(originalUrl + " should have " + clipBoard, editor.getPermissions(originalUrl).get(clipBoard)); - editor.renameCodebase(originalUrl, renamedUrl); + assertTrue(originalUrl + " should have " + clipBoard, editor.getPermissions(identifier).get(clipBoard)); + editor.modifyCodebase(identifier, renamedUrl); final Collection<String> afterRenamedCodebases = editor.getCodebases(); assertFalse("Editor should not contain old codebase: " + originalUrl, afterRenamedCodebases.contains(originalUrl)); assertTrue("Editor should contain new codebase name: " + renamedUrl, afterRenamedCodebases.contains(renamedUrl)); - assertTrue("Renamed " + renamedUrl + " should have " + clipBoard, editor.getPermissions(renamedUrl).get(clipBoard)); + final PolicyIdentifier renamedIdentifier = identifierFromCodebase(renamedUrl); + assertTrue("Renamed " + renamedUrl + " should have " + clipBoard, editor.getPermissions(renamedIdentifier).get(clipBoard)); } @Test @@ -139,54 +146,60 @@ final String copyUrl = "http://example.com"; final String pasteUrl = "http://example.com/example"; final PolicyEditorPermissions clipBoard = PolicyEditorPermissions.CLIPBOARD; - editor.addNewCodebase(copyUrl); - editor.setPermission(copyUrl, clipBoard, Boolean.TRUE); + final PolicyIdentifier identifier = identifierFromCodebase(copyUrl); + editor.addNewEntry(identifier); + editor.setPermission(identifier, clipBoard, Boolean.TRUE); final Collection<String> beforePasteCodebases = editor.getCodebases(); assertTrue("Editor should contain original codebase: " + copyUrl, beforePasteCodebases.contains(copyUrl)); - assertTrue(copyUrl + " should have " + clipBoard, editor.getPermissions(copyUrl).get(clipBoard)); - editor.copyCodebase(copyUrl); - editor.pasteCodebase(pasteUrl); + assertTrue(copyUrl + " should have " + clipBoard, editor.getPermissions(identifier).get(clipBoard)); + editor.copyEntry(identifier); + final PolicyIdentifier pastedIdentifier = identifierFromCodebase(pasteUrl); + editor.pasteEntry(pastedIdentifier); final Collection<String> afterPasteCodebases = editor.getCodebases(); assertTrue("Editor should still contain original codebase: " + copyUrl, afterPasteCodebases.contains(copyUrl)); assertTrue("Editor should also contain pasted codebase:" + pasteUrl, afterPasteCodebases.contains(pasteUrl)); - assertTrue(copyUrl + " should have " + clipBoard, editor.getPermissions(copyUrl).get(clipBoard)); - assertTrue(pasteUrl + " should have " + clipBoard, editor.getPermissions(pasteUrl).get(clipBoard)); + assertTrue(copyUrl + " should have " + clipBoard, editor.getPermissions(identifier).get(clipBoard)); + assertTrue(pasteUrl + " should have " + clipBoard, editor.getPermissions(pastedIdentifier).get(clipBoard)); } @Test public void testAddCustomPermissionNoActions() throws Exception { final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); - editor.addCustomPermission(codebase, customPermission); - assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(codebase).contains(customPermission)); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader"); + final PolicyIdentifier identifier = identifierFromCodebase(codebase); + editor.addCustomPermission(identifier, customPermission); + assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(identifier).contains(customPermission)); } @Test public void testAddCustomPermissionEmptyActions() throws Exception { final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", ""); - editor.addCustomPermission(codebase, customPermission); - assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(codebase).contains(customPermission)); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader", ""); + final PolicyIdentifier identifier = identifierFromCodebase(codebase); + editor.addCustomPermission(identifier, customPermission); + assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(identifier).contains(customPermission)); } @Test public void testClearCustomPermissionsNoActions() throws Exception { final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader"); - editor.addCustomPermission(codebase, customPermission); - assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(codebase).contains(customPermission)); - editor.clearCustomPermissions(codebase); - assertEquals(0, editor.getCustomPermissions(codebase).size()); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader"); + final PolicyIdentifier identifier = identifierFromCodebase(codebase); + editor.addCustomPermission(identifier, customPermission); + assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(identifier).contains(customPermission)); + editor.clearCustomPermissions(identifier); + assertEquals(0, editor.getCustomPermissions(identifier).size()); } @Test public void testClearCustomPermissionsEmptyActions() throws Exception { final String codebase = "http://example.com"; - final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", ""); - editor.addCustomPermission(codebase, customPermission); - assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(codebase).contains(customPermission)); - editor.clearCustomPermissions(codebase); - assertEquals(0, editor.getCustomPermissions(codebase).size()); + final CustomPolicyViewer.DisplayablePermission customPermission = new CustomPolicyViewer.DisplayablePermission("java.lang.RuntimePermission", "createClassLoader", ""); + final PolicyIdentifier identifier = identifierFromCodebase(codebase); + editor.addCustomPermission(identifier, customPermission); + assertTrue("Editor custom permissions should include " + customPermission + " but did not", editor.getCustomPermissions(identifier).contains(customPermission)); + editor.clearCustomPermissions(identifier); + assertEquals(0, editor.getCustomPermissions(identifier).size()); } @Test @@ -201,11 +214,11 @@ @Test public void testReturnedPermissionsMapIsCopy() throws Exception { - final Map<PolicyEditorPermissions, Boolean> original = editor.getPermissions(""); + final Map<PolicyEditorPermissions, Boolean> original = editor.getPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { original.put(perm, true); } - final Map<PolicyEditorPermissions, Boolean> second = editor.getPermissions(""); + final Map<PolicyEditorPermissions, Boolean> second = editor.getPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : second.entrySet()) { assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue()); } @@ -213,18 +226,19 @@ @Test public void testReturnedCustomPermissionsSetIsCopy() throws Exception { - final Collection<CustomPermission> original = editor.getCustomPermissions(""); + final Collection<PolicyParser.PermissionEntry> original = editor.getCustomPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); assertTrue("There should not be any custom permissions to start", original.isEmpty()); - original.add(new CustomPermission("java.io.FilePermission", "*", "write")); - final Collection<CustomPermission> second = editor.getCustomPermissions(""); + original.add(new CustomPolicyViewer.DisplayablePermission("java.io.FilePermission", "*", "write")); + final Collection<PolicyParser.PermissionEntry> second = editor.getCustomPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); assertTrue("The custom permission should not have been present", second.isEmpty()); } @Test public void testDefaultPermissionsAllFalse() throws Exception { - final Map<PolicyEditorPermissions, Boolean> defaultMap = editor.getPermissions(""); - editor.addNewCodebase("http://example.com"); - final Map<PolicyEditorPermissions, Boolean> addedMap = editor.getPermissions("http://example.com"); + final Map<PolicyEditorPermissions, Boolean> defaultMap = editor.getPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); + final PolicyIdentifier exampleIdentifier = identifierFromCodebase("http://example.com"); + editor.addNewEntry(exampleIdentifier); + final Map<PolicyEditorPermissions, Boolean> addedMap = editor.getPermissions(exampleIdentifier); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : defaultMap.entrySet()) { assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue()); } @@ -235,9 +249,10 @@ @Test public void testAllPermissionsRepresented() throws Exception { - final Map<PolicyEditorPermissions, Boolean> defaultMap = editor.getPermissions(""); - editor.addNewCodebase("http://example.com"); - final Map<PolicyEditorPermissions, Boolean> addedMap = editor.getPermissions("http://example.com"); + final Map<PolicyEditorPermissions, Boolean> defaultMap = editor.getPermissions(PolicyIdentifier.ALL_APPLETS_IDENTIFIER); + final PolicyIdentifier exampleIdentifier = identifierFromCodebase("http://example.com"); + editor.addNewEntry(exampleIdentifier); + final Map<PolicyEditorPermissions, Boolean> addedMap = editor.getPermissions(exampleIdentifier); assertTrue("Default codebase permissions keyset should be the same size as enum values set", defaultMap.keySet().size() == PolicyEditorPermissions.values().length); assertTrue("Added codebase permissions keyset should be the same size as enum values set", @@ -252,11 +267,11 @@ @Test public void testCodebaseTrailingSlashesDoNotMatch() throws Exception { - final Set<String> toAdd = new HashSet<String>(); - toAdd.add("http://redhat.com"); - toAdd.add("http://redhat.com/"); + final Set<String> toAdd = new HashSet<>(); + toAdd.add("http://example.com"); + toAdd.add("http://example.com/"); for (final String cb : toAdd) { - editor.addNewCodebase(cb); + editor.addNewEntry(identifierFromCodebase(cb)); } final Collection<String> codebases = editor.getCodebases(); assertTrue("Editor should have default codebase", codebases.contains(""));
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEntryTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEntryTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -37,52 +37,56 @@ package net.sourceforge.jnlp.security.policyeditor; import org.junit.Test; +import sun.security.provider.PolicyParser; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; /** * PolicyEntryTest does not test the various parsing scenarios as those are tested in PolicyEditorParsingTest */ public class PolicyEntryTest { - public static final String POLICY_ENTRY_STRING = "\ngrant codeBase \"http://example.com\" {\n" + - "\tpermission java.awt.AWTPermission \"accessClipboard\";\n" + - "};\n"; - public static final String INVALID_POLICY_STRING = "\ngrant codeBase http://example.com {\n" + - "\tpermission java.awt.AWTPermission \"accessClipboard\";" + - "}"; - @Test public void testGetCodebase() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - assertEquals("Codebase should equal input", codebase, policyEntry.getCodebase()); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); + assertEquals("Codebase should equal input", codebase, policyEntry.getPolicyIdentifier().getCodebase()); } @Test public void testNullCodebaseConvertsToEmpty() throws Exception { final String codebase = null; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - assertEquals("Null codebase should produce empty string", "", policyEntry.getCodebase()); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); + assertEquals("Null codebase should produce empty string", "", policyEntry.getPolicyIdentifier().getCodebase()); } @Test public void testGetPermissions() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); assertEquals("Permissions set should equal input", permissions, policyEntry.getPermissions()); } @@ -94,8 +98,12 @@ add(PolicyEditorPermissions.CLIPBOARD); add(PolicyEditorPermissions.NETWORK); }}; - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); assertEquals("Permissions set should equal input", permissions, policyEntry.getPermissions()); } @@ -103,8 +111,12 @@ public void testGetCustomPermissions() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final Set<? extends PolicyParser.PermissionEntry> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); assertEquals("Custom permissions set should equal input", customPermissions, policyEntry.getCustomPermissions()); } @@ -112,80 +124,63 @@ public void testGetCustomPermissions2() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = new HashSet<CustomPermission>(){{ - add(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - add(new CustomPermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER)); + final Set<? extends PolicyParser.PermissionEntry> customPermissions = new HashSet<CustomPolicyViewer.DisplayablePermission>(){{ + add(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + add(new CustomPolicyViewer.DisplayablePermission(PermissionType.RUNTIME_PERMISSION, PermissionTarget.CLASSLOADER)); }}; - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); assertEquals("Custom permissions set should equal input", customPermissions, policyEntry.getCustomPermissions()); } @Test(expected = NullPointerException.class) public void testEntryWithNullPermissions() throws Exception { final String codebase = "http://example.com"; - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - new PolicyEntry(codebase, null, customPermissions); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + new PolicyEntry.Builder() + .codebase(codebase) + .permissions(null) + .customPermissions(customPermissions) + .build(); } @Test(expected = NullPointerException.class) public void testEntryWithNullCustomPermissions() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - new PolicyEntry(codebase, permissions, null); + new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(null) + .build(); } - @Test + @Test(expected = NullPointerException.class) public void testNullPermissionsNotAllowed() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(null); - final Set<CustomPermission> customPermissions = Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - assertFalse("Permissions set should not contain null element", policyEntry.getPermissions().contains(null)); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY)); + new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); } @Test public void testNullCustomPermissionsNotAllowed() throws Exception { final String codebase = "http://example.com"; final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final Set<CustomPermission> customPermissions = Collections.singleton(null); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); + final Set<CustomPolicyViewer.DisplayablePermission> customPermissions = Collections.singleton(null); + final PolicyEntry policyEntry = new PolicyEntry.Builder() + .codebase(codebase) + .permissions(permissions) + .customPermissions(customPermissions) + .build(); assertFalse("Custom permissions set should not contain null element", policyEntry.getCustomPermissions().contains(null)); } - @Test - public void testFromString() throws Exception { - final PolicyEntry entry = PolicyEntry.fromString(POLICY_ENTRY_STRING); - assertEquals("Codebase should equal http://example.com", "http://example.com", entry.getCodebase()); - assertEquals("Permissions should be CLIPBOARD singleton", Collections.singleton(PolicyEditorPermissions.CLIPBOARD), entry.getPermissions()); - assertEquals("Custom permissions should be empty set", Collections.emptySet(), entry.getCustomPermissions()); - } - - @Test(expected = InvalidPolicyException.class) - public void testFromStringInvalid() throws Exception { - PolicyEntry.fromString(INVALID_POLICY_STRING); - } - - @Test - public void testValidatePolicy1() throws Exception { - assertTrue("Valid policy should pass validation", PolicyEntry.validatePolicy(Arrays.asList(POLICY_ENTRY_STRING.split("\\r?\\n")))); - } - - @Test - public void testValidatePolicy2() throws Exception { - assertTrue("Valid policy should pass validation", PolicyEntry.validatePolicy(POLICY_ENTRY_STRING)); - } - - @Test - public void testValidatePolicyInvalid1() throws Exception { - assertFalse("Invalid policy should not pass validation", PolicyEntry.validatePolicy(INVALID_POLICY_STRING)); - } - - @Test - public void testToString() { - final String codebase = "http://example.com"; - final Set<PolicyEditorPermissions> permissions = Collections.singleton(PolicyEditorPermissions.CLIPBOARD); - final PolicyEntry entry = new PolicyEntry(codebase, permissions, Collections.<CustomPermission>emptySet()); - assertEquals("Entry toString did not match expected output", POLICY_ENTRY_STRING, entry.toString()); - } - }
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyFileModelTest.java Wed Jul 29 18:08:16 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyFileModelTest.java Thu Jul 30 10:57:21 2015 -0400 @@ -39,6 +39,7 @@ import net.sourceforge.jnlp.util.FileUtils; import org.junit.Before; import org.junit.Test; +import sun.security.provider.PolicyParser; import java.io.File; import java.util.Collection; @@ -58,6 +59,20 @@ */ public class PolicyFileModelTest { + private static final String EXAMPLE_CODEBASE = "http://example.com"; + private static final String EXAMPLE_CA = "someCA"; + private static final Collection<PolicyParser.PrincipalEntry> EMPTY_PRINCIPALS = Collections.emptyList(); + private static final PolicyIdentifier EXAMPLE_IDENTIFIER = new PolicyIdentifier(EXAMPLE_CA, EMPTY_PRINCIPALS, EXAMPLE_CODEBASE); + private static final PolicyIdentifier INVALID_IDENTIFIER = new PolicyIdentifier(null, EMPTY_PRINCIPALS, "invalidURL"); + private static final String LINEBREAK = System.getProperty("line.separator"); + + private static final String EXAMPLE_POLICY_1 = "grant {" + LINEBREAK + + "\tpermission some.java.permission \"somePermission\";" + LINEBREAK + + "};" + LINEBREAK; + private static final String EXAMPLE_POLICY_2 = "grant {" + LINEBREAK + + "\tpermission some.other.java.permission \"somePermission\";" + LINEBREAK + + "};" + LINEBREAK; + private String tempFilePath; private PolicyFileModel model; @@ -104,113 +119,99 @@ @Test public void testFileHasChangedWithChange() throws Exception { assertFalse("Model should not report changes made initially", model.hasChanged()); - final String codebase = "http://example.com"; - final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD; - final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions); - FileUtils.saveFile(policyEntry.toString(), new File(tempFilePath)); + FileUtils.saveFile(EXAMPLE_POLICY_1, new File(tempFilePath)); model.openAndParsePolicyFile(); - final Collection<PolicyEditorPermissions> editorPermissions2 = Collections.singleton(PolicyEditorPermissions.ALL_AWT); - final PolicyEntry policyEntry2 = new PolicyEntry(codebase, editorPermissions2, customPermissions); - FileUtils.saveFile(policyEntry2.toString(), new File(tempFilePath)); + FileUtils.saveFile(EXAMPLE_POLICY_2, new File(tempFilePath)); assertTrue("File should be marked changed after being externally modified", model.hasChanged()); } @Test - public void testAddCodebase() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - assertEquals("Should have the codebase", Collections.singleton(codebase), model.getCodebases()); + public void testAddIdentifier() throws Exception { + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + assertEquals("Should have the identifier", Collections.singleton(EXAMPLE_IDENTIFIER), model.getIdentifiers()); } @Test - public void testRemoveCodebase() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - assertEquals("Should have the codebase " + codebase, Collections.singleton(codebase), model.getCodebases()); - model.removeCodebase(codebase); - assertEquals("Should not have any codebases after removed", Collections.emptySet(), model.getCodebases()); + public void testRemoveIdentifier() throws Exception { + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + assertEquals("Should have the identifier " + EXAMPLE_IDENTIFIER, Collections.singleton(EXAMPLE_IDENTIFIER), model.getIdentifiers()); + model.removeIdentifier(EXAMPLE_IDENTIFIER); + assertEquals("Should not have any identifiers after removed", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); } @Test public void testClearPermissions() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD; - model.setPermission(codebase, permission, true); - assertTrue("Expected permission " + permission, model.getPermission(codebase, permission)); + model.setPermission(EXAMPLE_IDENTIFIER, permission, true); + assertTrue("Expected permission " + permission, model.getPermission(EXAMPLE_IDENTIFIER, permission)); model.clearPermissions(); - assertFalse("Expected no permission " + permission, model.getPermission(codebase, permission)); - assertEquals("Expected no permissions ", Collections.emptyMap(), model.getCopyOfPermissions()); + assertFalse("Expected no permission " + permission, model.getPermission(EXAMPLE_IDENTIFIER, permission)); + assertEquals("Expected no permissions ", Collections.<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>>emptyMap(), model.getCopyOfPermissions()); } @Test public void testSettersAndGettersForPermission() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD; - model.setPermission(codebase, permission, true); - assertTrue("Expected permission " + permission, model.getPermission(codebase, permission)); + model.setPermission(EXAMPLE_IDENTIFIER, permission, true); + assertTrue("Expected permission " + permission, model.getPermission(EXAMPLE_IDENTIFIER, permission)); } @Test public void testClearCustomCodebase() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - model.addCustomPermissions(codebase, customPermissions); - assertEquals("Expected custom permission", customPermissions, model.getCopyOfCustomPermissions().get(codebase)); - model.clearCustomCodebase(codebase); - assertEquals("Custom permissions were expected to be empty", Collections.emptySet(), model.getCopyOfCustomPermissions().get(codebase)); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + final PolicyParser.PermissionEntry customPermission = new CustomPolicyViewer.DisplayablePermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); + final Collection<PolicyParser.PermissionEntry> customPermissions = Collections.singleton(customPermission); + model.addCustomPermissions(EXAMPLE_IDENTIFIER, customPermissions); + assertEquals("Expected custom permission", customPermissions, model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER)); + model.clearCustomIdentifier(EXAMPLE_IDENTIFIER); + final Set<PolicyParser.PermissionEntry> result = model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER); + assertTrue("Custom permissions were expected to be empty, was: " + result, result.isEmpty()); } @Test public void testClearCustomPermission() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - model.addCustomPermissions(codebase, customPermissions); - assertEquals("Expected custom permission", customPermissions, model.getCopyOfCustomPermissions().get(codebase)); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + final PolicyParser.PermissionEntry customPermission = new CustomPolicyViewer.DisplayablePermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); + final Collection<PolicyParser.PermissionEntry> customPermissions = Collections.singleton(customPermission); + model.addCustomPermissions(EXAMPLE_IDENTIFIER, customPermissions); + assertEquals("Expected custom permission", customPermissions, model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER)); model.clearCustomPermissions(); - assertEquals("Custom permissions were expected to be empty", null, model.getCopyOfCustomPermissions().get(codebase)); - assertEquals("All codebase custom permissions were expected to be empty", Collections.emptyMap(), model.getCopyOfCustomPermissions()); + assertEquals("Custom permissions were expected to be empty", null, model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER)); + final Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> result = model.getCopyOfCustomPermissions(); + assertTrue("All identifier custom permissions were expected to be empty, was: " + result, result.isEmpty()); } @Test public void testAddCustomPermissions() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); - final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission); - model.addCustomPermissions(codebase, customPermissions); - assertEquals("Expected file/user home/all-actions permission ", customPermissions, model.getCopyOfCustomPermissions().get(codebase)); - final CustomPermission customPermission2 = new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY); - final Collection<CustomPermission> customPermissions2 = Collections.singleton(customPermission2); - model.addCustomPermissions(codebase, customPermissions2); - assertTrue("Expected audio play permission ", model.getCopyOfCustomPermissions().get(codebase).contains(customPermission2)); - final HashSet<CustomPermission> customPermissionHashSet = new HashSet<>(); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + final PolicyParser.PermissionEntry customPermission = new CustomPolicyViewer.DisplayablePermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL); + final Collection<PolicyParser.PermissionEntry> customPermissions = Collections.singleton(customPermission); + model.addCustomPermissions(EXAMPLE_IDENTIFIER, customPermissions); + assertEquals("Expected file/user home/all-actions permission ", customPermissions, model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER)); + final CustomPolicyViewer.DisplayablePermission customPermission2 = new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY); + final Collection<CustomPolicyViewer.DisplayablePermission> customPermissions2 = Collections.singleton(customPermission2); + model.addCustomPermissions(EXAMPLE_IDENTIFIER, customPermissions2); + assertTrue("Expected audio play permission ", model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER).contains(customPermission2)); + final HashSet<PolicyParser.PermissionEntry> customPermissionHashSet = new HashSet<>(); customPermissionHashSet.add(customPermission); customPermissionHashSet.add(customPermission2); - assertEquals("Expected custom permission ", customPermissionHashSet, model.getCopyOfCustomPermissions().get(codebase)); + assertEquals("Expected custom permission ", customPermissionHashSet, model.getCopyOfCustomPermissions().get(EXAMPLE_IDENTIFIER)); } @Test public void testAllPermissionsAreFalseInitially() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - final Map<PolicyEditorPermissions, Boolean> policyEditorPermissions = model.getCopyOfPermissions().get(codebase); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + final Map<PolicyEditorPermissions, Boolean> policyEditorPermissions = model.getCopyOfPermissions().get(EXAMPLE_IDENTIFIER); for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : policyEditorPermissions.entrySet()) { assertFalse("Expected " + entry.getKey() + " to be false", entry.getValue()); } @@ -218,10 +219,9 @@ @Test public void testAllPermissionsAreInitialized() throws Exception { - assertEquals("Should not have any codebases initially", Collections.emptySet(), model.getCodebases()); - final String codebase = "http://example.com"; - model.addCodebase(codebase); - final Map<PolicyEditorPermissions, Boolean> policyEditorPermissions = model.getCopyOfPermissions().get(codebase); + assertEquals("Should not have any identifiers initially", Collections.<PolicyIdentifier>emptySet(), model.getIdentifiers()); + model.addIdentifier(EXAMPLE_IDENTIFIER); + final Map<PolicyEditorPermissions, Boolean> policyEditorPermissions = model.getCopyOfPermissions().get(EXAMPLE_IDENTIFIER); for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) { assertTrue(perm + " should have been present as a key", policyEditorPermissions.containsKey(perm)); } @@ -229,21 +229,21 @@ @Test public void testGetCopyOfPermissionsIsCopy() throws Exception { - final Map<String, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap = model.getCopyOfPermissions(); - assertEquals("Map should be initially empty", Collections.emptyMap(), codebasePermissionsMap); - codebasePermissionsMap.put("invalid codebase", Collections.singletonMap(PolicyEditorPermissions.CLIPBOARD, true)); - final Map<String, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap2 = model.getCopyOfPermissions(); - assertEquals("New copy should be initially empty", Collections.emptyMap(), codebasePermissionsMap2); + final Map<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap = model.getCopyOfPermissions(); + assertEquals("Map should be initially empty", Collections.<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>>emptyMap(), codebasePermissionsMap); + codebasePermissionsMap.put(INVALID_IDENTIFIER, Collections.singletonMap(PolicyEditorPermissions.CLIPBOARD, true)); + final Map<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap2 = model.getCopyOfPermissions(); + assertEquals("New copy should be initially empty", Collections.<PolicyIdentifier, Map<PolicyEditorPermissions, Boolean>>emptyMap(), codebasePermissionsMap2); assertNotEquals("Modified map should not equal newly copied map", codebasePermissionsMap, codebasePermissionsMap2); } @Test public void testGetCopyOfCustomPermissionsIsCopy() throws Exception { - final Map<String, Set<CustomPermission>> codebasePermissionsMap = model.getCopyOfCustomPermissions(); - assertEquals("Map should be initially empty", Collections.emptyMap(), codebasePermissionsMap); - codebasePermissionsMap.put("invalid codebase", Collections.singleton(new CustomPermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY))); - final Map<String, Set<CustomPermission>> codebasePermissionsMap2 = model.getCopyOfCustomPermissions(); - assertEquals("New copy should be initially empty", Collections.emptyMap(), codebasePermissionsMap2); + final Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> codebasePermissionsMap = model.getCopyOfCustomPermissions(); + assertEquals("Map should be initially empty", Collections.<PolicyIdentifier, Set<PolicyParser.PermissionEntry>>emptyMap(), codebasePermissionsMap); + codebasePermissionsMap.put(INVALID_IDENTIFIER, Collections.singleton((PolicyParser.PermissionEntry) new CustomPolicyViewer.DisplayablePermission(PermissionType.AUDIO_PERMISSION, PermissionTarget.PLAY))); + final Map<PolicyIdentifier, Set<PolicyParser.PermissionEntry>> codebasePermissionsMap2 = model.getCopyOfCustomPermissions(); + assertEquals("New copy should be initially empty", Collections.<PolicyIdentifier, Set<PolicyParser.PermissionEntry>>emptyMap(), codebasePermissionsMap2); assertNotEquals("Modified set should not equal newly copied set", codebasePermissionsMap, codebasePermissionsMap2); } }