Mercurial > hg > openjdk > icedtea > jdk7 > jdk
changeset 2484:3d51799b65a9
6948909: Jarsigner removes MANIFEST.MF info for badly packages jar's
Reviewed-by: mullan, xuelei
author | weijun |
---|---|
date | Thu, 06 May 2010 11:26:16 +0800 |
parents | 5dfa4f0429d8 |
children | 8834c3633f0b |
files | src/share/classes/sun/security/tools/JarSigner.java test/sun/security/tools/jarsigner/diffend.sh |
diffstat | 2 files changed, 172 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/sun/security/tools/JarSigner.java Wed May 05 13:18:31 2010 +0100 +++ b/src/share/classes/sun/security/tools/JarSigner.java Thu May 06 11:26:16 2010 +0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1123,6 +1123,8 @@ BASE64Encoder encoder = new JarBASE64Encoder(); Vector<ZipEntry> mfFiles = new Vector<ZipEntry>(); + boolean wasSigned = false; + for (Enumeration<? extends ZipEntry> enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); @@ -1132,6 +1134,11 @@ // out first mfFiles.addElement(ze); + if (SignatureFileVerifier.isBlockOrSF( + ze.getName().toUpperCase(Locale.ENGLISH))) { + wasSigned = true; + } + if (signatureRelated(ze.getName())) { // ignore signature-related and manifest files continue; @@ -1159,37 +1166,41 @@ if (mfModified) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); manifest.write(baos); - byte[] newBytes = baos.toByteArray(); - if (mfRawBytes != null - && oldAttr.equals(manifest.getMainAttributes())) { + if (wasSigned) { + byte[] newBytes = baos.toByteArray(); + if (mfRawBytes != null + && oldAttr.equals(manifest.getMainAttributes())) { - /* - * Note: - * - * The Attributes object is based on HashMap and can handle - * continuation columns. Therefore, even if the contents are - * not changed (in a Map view), the bytes that it write() - * may be different from the original bytes that it read() - * from. Since the signature on the main attributes is based - * on raw bytes, we must retain the exact bytes. - */ + /* + * Note: + * + * The Attributes object is based on HashMap and can handle + * continuation columns. Therefore, even if the contents are + * not changed (in a Map view), the bytes that it write() + * may be different from the original bytes that it read() + * from. Since the signature on the main attributes is based + * on raw bytes, we must retain the exact bytes. + */ - int newPos = findHeaderEnd(newBytes); - int oldPos = findHeaderEnd(mfRawBytes); + int newPos = findHeaderEnd(newBytes); + int oldPos = findHeaderEnd(mfRawBytes); - if (newPos == oldPos) { - System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); - } else { - // cat oldHead newTail > newBytes - byte[] lastBytes = new byte[oldPos + - newBytes.length - newPos]; - System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); - System.arraycopy(newBytes, newPos, lastBytes, oldPos, - newBytes.length - newPos); - newBytes = lastBytes; + if (newPos == oldPos) { + System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); + } else { + // cat oldHead newTail > newBytes + byte[] lastBytes = new byte[oldPos + + newBytes.length - newPos]; + System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); + System.arraycopy(newBytes, newPos, lastBytes, oldPos, + newBytes.length - newPos); + newBytes = lastBytes; + } } + mfRawBytes = newBytes; + } else { + mfRawBytes = baos.toByteArray(); } - mfRawBytes = newBytes; } // Write out the manifest @@ -1411,23 +1422,31 @@ } /** - * Find the position of an empty line inside bs + * Find the length of header inside bs. The header is a multiple (>=0) + * lines of attributes plus an empty line. The empty line is included + * in the header. */ private int findHeaderEnd(byte[] bs) { - // An empty line can be at the beginning... - if (bs.length > 1 && bs[0] == '\r' && bs[1] == '\n') { - return 0; - } - // ... or after another line - for (int i=0; i<bs.length-3; i++) { - if (bs[i] == '\r' && bs[i+1] == '\n' && - bs[i+2] == '\r' && bs[i+3] == '\n') { - return i; + // Initial state true to deal with empty header + boolean newline = true; // just met a newline + int len = bs.length; + for (int i=0; i<len; i++) { + switch (bs[i]) { + case '\r': + if (i < len && bs[i+1] == '\n') i++; + // fallthrough + case '\n': + if (newline) return i+1; //+1 to get length + newline = true; + break; + default: + newline = false; } } - // If header end is not found, return 0, - // which means no behavior change. - return 0; + // If header end is not found, it means the MANIFEST.MF has only + // the main attributes section and it does not end with 2 newlines. + // Returns the whole length so that it can be completely replaced. + return len; } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/tools/jarsigner/diffend.sh Thu May 06 11:26:16 2010 +0800 @@ -0,0 +1,113 @@ +# +# Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code 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 +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6948909 +# @summary Jarsigner removes MANIFEST.MF info for badly packages jar's +# + +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi +if [ "${TESTJAVA}" = "" ] ; then + echo "TESTJAVA not set. Test cannot execute." + echo "FAILED!!!" + exit 1 +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + NULL=/dev/null + PS=":" + FS="/" + CP="${FS}bin${FS}cp -f" + TMP=/tmp + ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + CP="cp -f" + TMP=/tmp + ;; + Windows_* ) + NULL=NUL + PS=";" + FS="\\" + CP="cp -f" + TMP="c:/temp" + ;; + * ) + echo "Unrecognized operating system!" + exit 1; + ;; +esac + +echo 1 > 1 +mkdir META-INF + +# Create a fake .RSA file so that jarsigner believes it's signed + +touch META-INF/x.RSA + +# A MANIFEST.MF using \n as newlines and no double newlines at the end + +cat > META-INF/MANIFEST.MF <<EOF +Manifest-Version: 1.0 +Created-By: 1.7.0-internal (Sun Microsystems Inc.) +Today: Monday +EOF + +# With the fake .RSA file, to trigger the if (wasSigned) block + +rm diffend.jar +zip diffend.jar META-INF/MANIFEST.MF META-INF/x.RSA 1 + +${TESTJAVA}${FS}bin${FS}jarsigner \ + -keystore ${TESTSRC}${FS}JarSigning.keystore \ + -storepass bbbbbb \ + -digestalg SHA1 \ + -signedjar diffend.new.jar \ + diffend.jar c + +unzip -p diffend.new.jar META-INF/MANIFEST.MF | grep Today || exit 1 + +# Without the fake .RSA file, to trigger the else block + +rm diffend.jar +zip diffend.jar META-INF/MANIFEST.MF 1 + +${TESTJAVA}${FS}bin${FS}jarsigner \ + -keystore ${TESTSRC}${FS}JarSigning.keystore \ + -storepass bbbbbb \ + -digestalg SHA1 \ + -signedjar diffend.new.jar \ + diffend.jar c + +unzip -p diffend.new.jar META-INF/MANIFEST.MF | grep Today || exit 2 +