From 8001e4f9fe567da99e968a50d6de7c6d4de3bb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Thu, 3 Mar 2022 22:50:11 +0100 Subject: [PATCH] #23507 Fixed signing jars downloaded by the appclient - several bugs - reproducible by several tests enabled in recent commits - removed incorrect wrapping of zip into zip - fixed error message, reported input file as an output - fixed closing streams - fixed removing corrupted files (stream could be still open) - fixed behavior when the glassfish-acc.xml file is missing --- .../server/core/jws/JWSAdapterManager.java | 124 ++++++-------- .../server/core/jws/JavaWebStartInfo.java | 25 ++- .../core/jws/servedcontent/ASJarSigner.java | 154 +++++++++--------- .../jws/servedcontent/AutoSignedContent.java | 17 +- .../StreamedAutoSignedStaticContent.java | 37 ++--- .../jws/servedcontent/LocalStrings.properties | 2 +- .../security/appclient/ConfigXMLParser.java | 19 +-- 7 files changed, 171 insertions(+), 207 deletions(-) diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java index 0b0eaea1655..ca09031cb4f 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -17,9 +18,12 @@ package org.glassfish.appclient.server.core.jws; import com.sun.enterprise.config.serverbeans.Config; -import org.glassfish.orb.admin.config.IiopService; import com.sun.enterprise.deployment.ApplicationClientDescriptor; -import com.sun.logging.LogDomains; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; + import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; @@ -38,8 +42,7 @@ import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; -import jakarta.inject.Inject; -import jakarta.inject.Named; + import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.api.container.EndpointRegistrationException; import org.glassfish.api.container.RequestDispatcher; @@ -52,12 +55,11 @@ import org.glassfish.appclient.server.core.jws.servedcontent.SimpleDynamicContentImpl; import org.glassfish.appclient.server.core.jws.servedcontent.StaticContent; import org.glassfish.enterprise.iiop.api.GlassFishORBFactory; -import org.glassfish.internal.api.ServerContext; - -import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PostConstruct; -import jakarta.inject.Singleton; +import org.glassfish.internal.api.ServerContext; import org.glassfish.logging.annotation.LogMessageInfo; +import org.glassfish.orb.admin.config.IiopService; +import org.jvnet.hk2.annotations.Service; /** * Handles all management of the HTTP adapters created to support Java Web @@ -98,39 +100,35 @@ public class JWSAdapterManager implements PostConstruct { private static final String LINE_SEP = System.getProperty("line.separator"); - private static final List DO_NOT_SERVE_LIST = - Collections.EMPTY_LIST; //Arrays.asList("glassfish/modules/jaxb-osgi.jar"); + private static final List DO_NOT_SERVE_LIST = Collections.emptyList(); private static final String JWS_SIGNED_SYSTEM_JARS_ROOT = "java-web-start/___system"; private static final String JWS_SIGNED_DOMAIN_JARS_ROOT = "java-web-start/___domain"; - private static final String JAVA_WEB_START_CONTEXT_ROOT_PROPERTY_NAME = - "javaWebStartContextRoot"; + private static final String JAVA_WEB_START_CONTEXT_ROOT_PROPERTY_NAME = "javaWebStartContextRoot"; + /** * maps "(aliasName)/(systemJarRelativePath)" to AutoSignedContent for * the system JAR as signed by the cert linked to the alias */ - private final Map appLevelSignedSystemContent = - new HashMap(); + private final Map appLevelSignedSystemContent = new HashMap<>(); - private URI installRootURI = null; + private URI installRootURI; - private AppClientHTTPAdapter systemAdapter = null; + private AppClientHTTPAdapter systemAdapter; - private Logger logger = null; + private Logger logger; private IiopService iiopService; - private final HashMap> contributingAppClients = - new HashMap>(); + private final HashMap> contributingAppClients = new HashMap<>(); - private final ConcurrentHashMap httpAdapters = new - ConcurrentHashMap(); + private final ConcurrentHashMap httpAdapters = new ConcurrentHashMap<>(); - private URI umbrellaRootURI = null; - private File umbrellaRoot = null; - private File systemLevelSignedJARsRoot = null; - private File domainLevelSignedJARsRoot = null; + private URI umbrellaRootURI; + private File umbrellaRoot; + private File systemLevelSignedJARsRoot; + private File domainLevelSignedJARsRoot; @LogMessageInfo( message = "Error starting the adapter to serve static system-level content", @@ -227,7 +225,7 @@ Map addStaticSystemContent( * adapter which serves files from the installation, as opposed to * files from the domain or files from a specific app. */ - Map result = new HashMap(); + Map result = new HashMap<>(); File gfClientJAR = gfClientJAR(); final String classPathExpr = getGFClientModuleClassPath(gfClientJAR); @@ -277,39 +275,39 @@ public boolean accept(File pathname) { return result; } + File gfClientJAR() { - return new File( - libDir(), - "gf-client.jar"); + return new File(libDir(), "gf-client.jar"); } + File gfClientModuleJAR() { - return new File( - modulesDir(), - "gf-client-module.jar"); + return new File(modulesDir(), "gf-client-module.jar"); } + private synchronized File modulesDir() { return new File(new File(installRootURI), "modules"); } + private synchronized File libDir() { return new File(new File(installRootURI), "lib"); } - private AutoSignedContent systemJarSignedContent ( - final File unsignedFile, - final String signingAlias) throws FileNotFoundException { + + private AutoSignedContent systemJarSignedContent(final File unsignedFile, final String signingAlias) + throws FileNotFoundException { final String relativeURI = relativeSystemPath(unsignedFile.toURI()); - final File signedFile = new File(signedSystemContentAliasDir(signingAlias), - relativeURI); + final File signedFile = new File(signedSystemContentAliasDir(signingAlias), relativeURI); return new AutoSignedContent(unsignedFile, signedFile, signingAlias, jarSigner, relativeURI, MANIFEST_APP_NAME_FOR_SYSTEM_FILES); } - Map addDynamicSystemContent(final List systemJARRelativeURIs, - final String signingAlias) throws IOException { - final Map result = new HashMap(); + + Map addDynamicSystemContent(final List systemJARRelativeURIs, + final String signingAlias) throws IOException { + final Map result = new HashMap<>(); final String template = JavaWebStartInfo.textFromURL( "/org/glassfish/appclient/server/core/jws/templates/systemJarsDocumentTemplate.jnlp"); final StringBuilder sb = new StringBuilder(); @@ -328,8 +326,7 @@ Map addDynamicSystemContent(final List systemJARR } private String systemPath(final URI systemFileURI) { - return //NamingConventions.JWSAPPCLIENT_SYSTEM_PREFIX + "/" + - relativeSystemPath(systemFileURI); + return relativeSystemPath(systemFileURI); } String systemPath(final URI systemFileURI, final String signingAlias) { @@ -546,23 +543,16 @@ synchronized File signedSystemContentAliasDir(final String alias) { public String contextRootForAppAdapter(final String appName) { final AppClientHTTPAdapter adapter = httpAdapters.get(appName); - if (adapter != null) { - return adapter.contextRoot(); - } else { - return null; - } + return adapter == null ? null : adapter.contextRoot(); } - private synchronized void addContributorToAppLevelAdapter( - final String appName, - final AppClientServerApplication contributor) { - /* - * Record that the calling app client server app has contributed content - * to the Grizzly adapter. - */ + + private synchronized void addContributorToAppLevelAdapter(final String appName, + final AppClientServerApplication contributor) { + // Record that the calling app client server app has contributed content to the Grizzly adapter. Set contributorsToAppLevelAdapter = contributingAppClients.get(appName); if (contributorsToAppLevelAdapter == null) { - contributorsToAppLevelAdapter = new HashSet(); + contributorsToAppLevelAdapter = new HashSet<>(); contributingAppClients.put(appName, contributorsToAppLevelAdapter); } contributorsToAppLevelAdapter.add(contributor); @@ -572,13 +562,9 @@ public synchronized void removeContentForAppClient(final String appName, final String clientURIWithinEAR, final AppClientServerApplication contributor) throws EndpointRegistrationException { - /* - * Remove the adapter for the user-friendly context root. - */ + // Remove the adapter for the user-friendly context root. removeAdapter(userFriendlyContextRoot(contributor)); - removeContributorToAppLevelAdapter(appName, contributor); - appClientDeployer.removeContextRoot(appName, clientURIWithinEAR); } @@ -602,21 +588,17 @@ private synchronized void removeContributorToAppLevelAdapter( } } - private synchronized void removeAdapter(final String contextRoot) - throws EndpointRegistrationException { + + private synchronized void removeAdapter(final String contextRoot) throws EndpointRegistrationException { requestDispatcher.unregisterEndpoint(contextRoot); } - private String getGFClientModuleClassPath(final File gfClientJAR) throws IOException { - final JarFile jf = new JarFile(gfClientJAR); - try { - final Manifest mf = jf.getManifest(); - Attributes mainAttrs = mf.getMainAttributes(); - return mainAttrs.getValue(Attributes.Name.CLASS_PATH); - } finally - { - jf.close(); + private String getGFClientModuleClassPath(final File gfClientJAR) throws IOException { + try (JarFile jf = new JarFile(gfClientJAR)) { + final Manifest mf = jf.getManifest(); + Attributes mainAttrs = mf.getMainAttributes(); + return mainAttrs.getValue(Attributes.Name.CLASS_PATH); } } diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java index 53892b3a4d8..b7889f04c31 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -18,7 +19,6 @@ import com.sun.enterprise.deployment.ApplicationClientDescriptor; import com.sun.enterprise.universal.i18n.LocalStringsImpl; -import com.sun.logging.LogDomains; import java.beans.PropertyChangeEvent; import java.io.File; import java.io.FileNotFoundException; @@ -133,8 +133,8 @@ public class JavaWebStartInfo implements ConfigListener { private String signingAlias; - final private Map staticContent = new HashMap(); - final private Map dynamicContent = new HashMap(); + final private Map staticContent = new HashMap<>(); + final private Map dynamicContent = new HashMap<>(); private static final String JNLP_MIME_TYPE = "application/x-java-jnlp-file"; @@ -423,7 +423,7 @@ private Set addClientContentToHTTPAdapters() throws EndpointRegistratio dch.addDeveloperContentFromPath(developerJNLPDoc); - Set result = new HashSet(staticContent.values()); + Set result = new HashSet<>(staticContent.values()); result.addAll(dynamicContent.values()); jwsAdapterManager.addContentForAppClient( @@ -498,7 +498,7 @@ private void initClientStaticContent() private void addSignedSystemContent( ) throws FileNotFoundException, IOException { - final List systemJARRelativeURIs = new ArrayList(); + final List systemJARRelativeURIs = new ArrayList<>(); final Map addedStaticContent = jwsAdapterManager.addStaticSystemContent( systemJARRelativeURIs, @@ -663,17 +663,12 @@ public File signedFileForProvidedAppFile(final File unsignedFile) { public static File signedFileForProvidedAppFile(final URI relURI, final File unsignedFile, final AppClientDeployerHelper helper, - final DeploymentContext dc) { /* - * Place a signed file for a developer-provided file at - * - * generated/xml/(appName)/signed/(path-within-app-of-unsigned-file) - * - * - */ + final DeploymentContext dc) { + // Place a signed file for a developer-provided file at + // generated/xml/(appName)/signed/(path-within-app-of-unsigned-file) final File rootForSignedFilesInApp = helper.rootForSignedFilesInApp(); mkdirs(rootForSignedFilesInApp); final URI signedFileURI = rootForSignedFilesInApp.toURI().resolve(relURI); - return new File(signedFileURI); } @@ -805,7 +800,7 @@ private VendorInfo vendorInfo() { } public static class VendorInfo { - private String vendorStringFromDescriptor; + private final String vendorStringFromDescriptor; private String vendor = ""; private String imageURIString = ""; private String splashImageURIString = ""; @@ -858,7 +853,7 @@ public String JNLPSplashImageURI() { @Override public UnprocessedChangeEvents changed(PropertyChangeEvent[] events) { /* Record any events we tried to process but could not. */ - List unprocessedEvents = new ArrayList(); + List unprocessedEvents = new ArrayList<>(); for (PropertyChangeEvent event : events) { try { diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/ASJarSigner.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/ASJarSigner.java index 939cd7bf2af..875ec8cd26e 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/ASJarSigner.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/ASJarSigner.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -18,34 +19,37 @@ import com.sun.enterprise.server.pluggable.SecuritySupport; import com.sun.enterprise.util.i18n.StringManager; -import com.sun.logging.LogDomains; -import static java.util.Arrays.asList; +import jakarta.inject.Singleton; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.OutputStream; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; import java.security.cert.CertPath; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.ZipOutputStream; -import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PostConstruct; -import jakarta.inject.Singleton; +import org.jvnet.hk2.annotations.Service; + import jdk.security.jarsigner.JarSigner; -import jdk.security.jarsigner.JarSignerException; -import org.glassfish.appclient.server.core.jws.JavaWebStartInfo; +import static java.util.Arrays.asList; +import static org.glassfish.appclient.server.core.jws.JavaWebStartInfo.APPCLIENT_SERVER_LOGMESSAGE_RESOURCE; +import static org.glassfish.appclient.server.core.jws.JavaWebStartInfo.APPCLIENT_SERVER_MAIN_LOGGER; /** * Signs a specified JAR file. @@ -66,73 +70,53 @@ public class ASJarSigner implements PostConstruct { /** property name optionally set by the admin in domain.xml to select an alias for signing */ public static final String USER_SPECIFIED_ALIAS_PROPERTYNAME = "com.sun.aas.jws.signing.alias"; - /** keystore type for JKS keystores */ - private static final String JKS_KEYSTORE_TYPE_VALUE = "jks"; - /** default alias for signing if the admin does not specify one */ private static final String DEFAULT_ALIAS_VALUE = "s1as"; - private static final String DEFAULT_DIGEST_ALGORITHM = "SHA-1"; - private static final String DEFAULT_SIGNATURE_ALGORITHM = "SHA1withRSA"; + private static final String DEFAULT_DIGEST_ALGORITHM = "SHA-256"; + private static final String DEFAULT_SIGNATURE_ALGORITHM = "SHA256withRSA"; private static final SecuritySupport securitySupport = SecuritySupport.getDefaultInstance(); -// /** user-specified signing alias */ -// private final String userAlias; // = System.getProperty(USER_SPECIFIED_ALIAS_PROPERTYNAME); - private static final StringManager localStrings = StringManager.getManager(ASJarSigner.class); private Logger logger; @Override public void postConstruct() { - logger =Logger.getLogger(JavaWebStartInfo.APPCLIENT_SERVER_MAIN_LOGGER, JavaWebStartInfo.APPCLIENT_SERVER_LOGMESSAGE_RESOURCE); + logger = Logger.getLogger(APPCLIENT_SERVER_MAIN_LOGGER, APPCLIENT_SERVER_LOGMESSAGE_RESOURCE); } + /** - *Creates a signed jar from the specified unsigned jar. - *@param unsignedJar the unsigned JAR file - *@param signedJar the signed JAR to be created - *@param attrs additional attributes to be added to the JAR's manifest main section - *@return the elapsed time to sign the JAR (in milliseconds) - *@throws Exception getting the keystores from SSLUtils fails + * Creates a signed jar from the specified unsigned jar. + * + * @param unsignedJar the unsigned JAR file + * @param signedJar the signed JAR to be created + * @param attrs additional attributes to be added to the JAR's manifest main section + * @return the elapsed time to sign the JAR (in milliseconds) + * @throws Exception getting the keystores from SSLUtils fails */ - public long signJar(final File unsignedJar, final File signedJar, - String alias, Attributes attrs) throws Exception { - - final ZipOutputStream zout = new ZipOutputStream( - new FileOutputStream(signedJar)); - try { - final long result = signJar(unsignedJar, zout, alias, attrs, Collections.EMPTY_MAP); - return result; - } catch (Exception ex) { - /* - *In case of any problems, make sure there is no ill-formed signed - *jar file left behind. - */ - if ( signedJar.exists() && ! signedJar.delete()) { - logger.log(Level.FINE, "Could not remove generated signed JAR {0} after JarSigner reported an error", - signedJar.getAbsolutePath()); - } - throw ex; - } finally { - zout.close(); + public long signJar(final File unsignedJar, final File signedJar, String alias, Attributes attrs) throws Exception { + try (OutputStream zout = new BufferedOutputStream(new FileOutputStream(signedJar))) { + return signJar(unsignedJar, zout, alias, attrs, Collections.emptyMap()); } } + /** * Creates a signed ZIP output stream from an unsigned JAR and, possibly, additional content. + * * @param unsignedJar JAR file containing most of the content to sign and return * @param signedJar already-opened ZipOutputStream to receive the signed content * @param alias the alias with which to identify the cert for signing the output * @param attrs additional manifest attributes to add * @param additionalContent additional JAR entries to add - * @return - * @throws Exception + * @return the elapsed time to sign the JAR (in milliseconds) + * @throws IllegalStateException */ - public long signJar(final File unsignedJar, final ZipOutputStream signedJar, - String alias, final Attributes attrs, final Map additionalContent) throws Exception { - + public long signJar(final File unsignedJar, final OutputStream signedJar, String alias, final Attributes attrs, + final Map additionalContent) throws IllegalStateException { if (alias == null) { alias = DEFAULT_ALIAS_VALUE; } @@ -140,48 +124,56 @@ public long signJar(final File unsignedJar, final ZipOutputStream signedJar, long duration = 0; synchronized(this) { try { - Certificate[] certificates = null; - PrivateKey privateKey = null; - KeyStore[] keyStores = securitySupport.getKeyStores(); - for (int i = 0; i < keyStores.length; i++) { - privateKey = securitySupport.getPrivateKeyForAlias(alias, i); - if (privateKey != null) { - certificates = keyStores[i].getCertificateChain(alias); - } - } - - CertPath certPath = CertificateFactory.getInstance("X.509").generateCertPath(asList(certificates)); - - JarSigner signer = new JarSigner.Builder(privateKey, certPath) - .digestAlgorithm(DEFAULT_DIGEST_ALGORITHM) - .signatureAlgorithm(DEFAULT_SIGNATURE_ALGORITHM) - .build(); - + JarSigner signer = createJarSigner(alias); // TODO: add Attributes to Manifest and additionalContent - - signer.sign(new JarFile(unsignedJar), signedJar); - - } catch (Throwable t) { - /* - *The jar signer will have written some information to System.out - */ - throw new Exception(localStrings.getString("jws.sign.errorSigning", - unsignedJar.getAbsolutePath(), alias), t); + try (JarFile jarFile = new JarFile(unsignedJar)) { + signer.sign(jarFile, signedJar); + } + } catch (Exception e) { + throw new IllegalStateException( + localStrings.getString("jws.sign.errorSigning", unsignedJar.getAbsolutePath(), alias), e); } finally { duration = System.currentTimeMillis() - startTime; logger.log(Level.FINE, "Signing {0} took {1} ms", - new Object[]{unsignedJar.getAbsolutePath(), duration}); + new Object[] {unsignedJar.getAbsolutePath(), duration}); } } return duration; } + + private JarSigner createJarSigner(final String alias) + throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, CertificateException { + Certificate[] certificates = null; + PrivateKey privateKey = null; + KeyStore[] keyStores = securitySupport.getKeyStores(); + for (int i = 0; i < keyStores.length; i++) { + privateKey = securitySupport.getPrivateKeyForAlias(alias, i); + if (privateKey == null) { + continue; + } + certificates = keyStores[i].getCertificateChain(alias); + if (certificates != null && certificates.length > 0) { + break; + } + } + if (certificates == null) { + throw new IllegalStateException("No certificates available for the alias: " + alias); + } + CertPath certPath = CertificateFactory.getInstance("X.509").generateCertPath(asList(certificates)); + return new JarSigner.Builder(privateKey, certPath) + .digestAlgorithm(DEFAULT_DIGEST_ALGORITHM) + .signatureAlgorithm(DEFAULT_SIGNATURE_ALGORITHM) + .build(); + } + + /** - *Wraps any underlying exception. - *

- *This is primarily used to insulate calling logic from - *the large variety of exceptions that can occur during signing - *from which the caller cannot really recover. + * Wraps any underlying exception. + *

+ * This is primarily used to insulate calling logic from + * the large variety of exceptions that can occur during signing + * from which the caller cannot really recover. */ public static class ASJarSignerException extends Exception { public ASJarSignerException(String msg, Throwable t) { diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/AutoSignedContent.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/AutoSignedContent.java index 19c22c25a06..73d6990174a 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/AutoSignedContent.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/AutoSignedContent.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,17 +17,15 @@ package org.glassfish.appclient.server.core.jws.servedcontent; -import com.sun.enterprise.util.net.NetUtils; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; import java.text.MessageFormat; import java.util.ResourceBundle; import java.util.jar.Attributes; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Represents otherwise fixed content that must be automatically signed @@ -64,7 +63,6 @@ static Attributes createJWSAttrs(final URI requestURI, final String appName) { private final File signedFile; private final String userProvidedAlias; private final ASJarSigner jarSigner; - private final URI relativeURI; private final String appName; public AutoSignedContent(final File unsignedFile, @@ -80,7 +78,6 @@ public AutoSignedContent(final File unsignedFile, this.signedFile = signedFile; this.userProvidedAlias = userProvidedAlias; this.jarSigner = jarSigner; - this.relativeURI = URI.create(relativeURI); this.appName = appName; } @@ -151,7 +148,15 @@ private void createSignedFile(final URI requestURI) throws Exception { } } final Attributes attrs = createJWSAttrs(requestURI, appName); - jarSigner.signJar(unsignedFile, signedFile, userProvidedAlias, attrs); + try { + jarSigner.signJar(unsignedFile, signedFile, userProvidedAlias, attrs); + } catch (Exception e) { + // File may be already created, but probably has corrupted content. + if (signedFile.exists()) { + Files.deleteIfExists(signedFile.toPath()); + } + throw e; + } } @Override diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/StreamedAutoSignedStaticContent.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/StreamedAutoSignedStaticContent.java index 79d8cfe2bf8..f9bb2249cd9 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/StreamedAutoSignedStaticContent.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/servedcontent/StreamedAutoSignedStaticContent.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -22,6 +23,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; @@ -105,35 +107,26 @@ public void process(String relativeURIString, Request gReq, Response gResp) thro * Instead we'll just write to the output stream and Grizzly will * chunk it for us if needed. */ - final ZipOutputStream zos = new ZipOutputStream(gResp.getOutputStream()); logger.log(Level.FINE, "Request's session contains cached JNLP"); final byte[] jnlpContent = (byte[]) jwsObj; - final Map addedContent = new HashMap(); + final Map addedContent = new HashMap<>(); addedContent.put(SIGNED_JNLP_PATH, jnlpContent); try { - jarSigner().signJar(unsignedFile(), zos, userProvidedAlias(), createJWSAttrs(AppClientHTTPAdapter.requestURI(gReq), appName()), addedContent); - /* - * Create an on-disk copy of the signed JAR for debugging purposes - * if logging is detailed enough. - */ + jarSigner().signJar(unsignedFile(), gResp.getOutputStream(), userProvidedAlias(), + createJWSAttrs(AppClientHTTPAdapter.requestURI(gReq), appName()), addedContent); + // Create an on-disk copy of the signed JAR for debugging purposes if logging is detailed enough. if (logger.isLoggable(Level.FINEST)) { - final File debugSignedJARFile = new File(unsignedFile().getAbsolutePath()+".debug"); - final ZipOutputStream dbgZos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(debugSignedJARFile))); - try { - jarSigner().signJar(unsignedFile(), dbgZos, userProvidedAlias(), createJWSAttrs(AppClientHTTPAdapter.requestURI(gReq), appName()), addedContent); - } finally { - dbgZos.close(); + final File debugSignedJARFile = new File(unsignedFile().getAbsolutePath() + ".debug"); + try (ZipOutputStream dbgZos = new ZipOutputStream( + new BufferedOutputStream(new FileOutputStream(debugSignedJARFile)))) { + jarSigner().signJar(unsignedFile(), dbgZos, userProvidedAlias(), + createJWSAttrs(AppClientHTTPAdapter.requestURI(gReq), appName()), addedContent); } logger.log(Level.FINEST, "Created on-disk signed JAR {0}", debugSignedJARFile.getAbsolutePath()); } - zos.close(); - } catch (IOException ioex) { - throw ioex; - } catch (Exception ex) { + } catch (URISyntaxException ex) { throw new IOException(ex); - } finally { - zos.close(); } } @@ -156,10 +149,8 @@ private String contentType(final File file) { if (dot > 0) { String ext = substr.substring(dot + 1); - String ct = MimeType.get(ext); - return ct; - } else { - return MimeType.get("html"); + return MimeType.get(ext); } + return MimeType.get("html"); } } diff --git a/appserver/appclient/server/core/src/main/resources/org/glassfish/appclient/server/core/jws/servedcontent/LocalStrings.properties b/appserver/appclient/server/core/src/main/resources/org/glassfish/appclient/server/core/jws/servedcontent/LocalStrings.properties index a9855f5e7d4..93093007a44 100644 --- a/appserver/appclient/server/core/src/main/resources/org/glassfish/appclient/server/core/jws/servedcontent/LocalStrings.properties +++ b/appserver/appclient/server/core/src/main/resources/org/glassfish/appclient/server/core/jws/servedcontent/LocalStrings.properties @@ -22,7 +22,7 @@ jws.sign.noUnsignedJar=Unsigned jar {0} marked for signing does not exist jws.sign.userAliasAbsent=User-specified alias {0} to be used for signing JAR files was not found in any keystore; attempting to use default alias instead jws.sign.aliasNotFound=Alias {0} not found in keystore(s); aborting jws.sign.aliasFoundMult=Alias {0} to be used for signing JAR files was found in more than one keystore; using the first occurrence from the keystores with these providers: {1} -jws.sign.errorSigning=Error attempting to create signed jar {0} with alias {1} +jws.sign.errorSigning=Error attempting to sign jar {0} with alias {1} jws.sign.errorCreatingDir=Unknown error attempting to create directory {0} to contain signed jar jws.sign.keyNotPrivate=Key for alias {0} is not a private key, as required jws.sign.notX509Cert=Certificate associated with alias {0} is not an X509 certificate, as required diff --git a/appserver/security/appclient.security/src/main/java/com/sun/enterprise/security/appclient/ConfigXMLParser.java b/appserver/security/appclient.security/src/main/java/com/sun/enterprise/security/appclient/ConfigXMLParser.java index 8e0aa43b61e..955b1f01e28 100644 --- a/appserver/security/appclient.security/src/main/java/com/sun/enterprise/security/appclient/ConfigXMLParser.java +++ b/appserver/security/appclient.security/src/main/java/com/sun/enterprise/security/appclient/ConfigXMLParser.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -18,6 +19,7 @@ import static java.util.regex.Matcher.quoteReplacement; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -59,8 +61,8 @@ public class ConfigXMLParser implements ConfigParser { private static Pattern PROPERTY_PATTERN = Pattern.compile("\\$\\{\\{(.*?)}}|\\$\\{(.*?)}"); // configuration info - private Map configMap = new HashMap(); - private Set layersWithDefault = new HashSet(); + private final Map configMap = new HashMap(); + private final Set layersWithDefault = new HashSet<>(); private List msgSecConfigs = null; private static final String ACC_XML = "glassfish-acc.xml.url"; @@ -90,10 +92,12 @@ private void processClientConfigContext(Map newConfig) throws IOException { } + @Override public Map getConfigMap() { return configMap; } + @Override public Set getLayersWithDefault() { return layersWithDefault; } @@ -218,23 +222,18 @@ private MessagePolicy parsePolicy(Object policy) { return AuthMessagePolicy.getMessagePolicy(authSource, authRecipient); } + @Override public void initialize(Object config) throws IOException { String sun_acc = System.getProperty(ACC_XML, "glassfish-acc.xml"); List msgconfigs = null; - if (Globals.getDefaultHabitat() == null && sun_acc != null) { - InputStream is = null; - try { - is = new FileInputStream(sun_acc); + if (Globals.getDefaultHabitat() == null && sun_acc != null && new File(sun_acc).exists()) { + try (InputStream is = new FileInputStream(sun_acc)) { JAXBContext jc = JAXBContext.newInstance(ClientContainer.class); Unmarshaller u = jc.createUnmarshaller(); ClientContainer cc = (ClientContainer) u.unmarshal(is); msgconfigs = cc.getMessageSecurityConfig(); } catch (JAXBException ex) { _logger.log(Level.SEVERE, null, ex); - } finally { - if (is != null) { - is.close(); - } } } else { Util util = Util.getInstance();