Merge
This commit is contained in:
commit
fcbc383092
@ -2051,6 +2051,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @param n shift distance, in bits.
|
* @param n shift distance, in bits.
|
||||||
* @return {@code this << n}
|
* @return {@code this << n}
|
||||||
|
* @throws ArithmeticException if the shift distance is {@code
|
||||||
|
* Integer.MIN_VALUE}.
|
||||||
* @see #shiftRight
|
* @see #shiftRight
|
||||||
*/
|
*/
|
||||||
public BigInteger shiftLeft(int n) {
|
public BigInteger shiftLeft(int n) {
|
||||||
@ -2058,8 +2060,13 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
return ZERO;
|
return ZERO;
|
||||||
if (n==0)
|
if (n==0)
|
||||||
return this;
|
return this;
|
||||||
if (n<0)
|
if (n<0) {
|
||||||
return shiftRight(-n);
|
if (n == Integer.MIN_VALUE) {
|
||||||
|
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
|
||||||
|
} else {
|
||||||
|
return shiftRight(-n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nInts = n >>> 5;
|
int nInts = n >>> 5;
|
||||||
int nBits = n & 0x1f;
|
int nBits = n & 0x1f;
|
||||||
@ -2097,13 +2104,20 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @param n shift distance, in bits.
|
* @param n shift distance, in bits.
|
||||||
* @return {@code this >> n}
|
* @return {@code this >> n}
|
||||||
|
* @throws ArithmeticException if the shift distance is {@code
|
||||||
|
* Integer.MIN_VALUE}.
|
||||||
* @see #shiftLeft
|
* @see #shiftLeft
|
||||||
*/
|
*/
|
||||||
public BigInteger shiftRight(int n) {
|
public BigInteger shiftRight(int n) {
|
||||||
if (n==0)
|
if (n==0)
|
||||||
return this;
|
return this;
|
||||||
if (n<0)
|
if (n<0) {
|
||||||
return shiftLeft(-n);
|
if (n == Integer.MIN_VALUE) {
|
||||||
|
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
|
||||||
|
} else {
|
||||||
|
return shiftLeft(-n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nInts = n >>> 5;
|
int nInts = n >>> 5;
|
||||||
int nBits = n & 0x1f;
|
int nBits = n & 0x1f;
|
||||||
|
@ -101,11 +101,21 @@ public abstract class CookieHandler {
|
|||||||
* Gets all the applicable cookies from a cookie cache for the
|
* Gets all the applicable cookies from a cookie cache for the
|
||||||
* specified uri in the request header.
|
* specified uri in the request header.
|
||||||
*
|
*
|
||||||
* HTTP protocol implementers should make sure that this method is
|
* <P>The {@code URI} passed as an argument specifies the intended use for
|
||||||
* called after all request headers related to choosing cookies
|
* the cookies. In particular the scheme should reflect whether the cookies
|
||||||
* are added, and before the request is sent.
|
* will be sent over http, https or used in another context like javascript.
|
||||||
|
* The host part should reflect either the destination of the cookies or
|
||||||
|
* their origin in the case of javascript.</P>
|
||||||
|
* <P>It is up to the implementation to take into account the {@code URI} and
|
||||||
|
* the cookies attributes and security settings to determine which ones
|
||||||
|
* should be returned.</P>
|
||||||
*
|
*
|
||||||
* @param uri a <code>URI</code> to send cookies to in a request
|
* <P>HTTP protocol implementers should make sure that this method is
|
||||||
|
* called after all request headers related to choosing cookies
|
||||||
|
* are added, and before the request is sent.</P>
|
||||||
|
*
|
||||||
|
* @param uri a <code>URI</code> representing the intended use for the
|
||||||
|
* cookies
|
||||||
* @param requestHeaders - a Map from request header
|
* @param requestHeaders - a Map from request header
|
||||||
* field names to lists of field values representing
|
* field names to lists of field values representing
|
||||||
* the current request headers
|
* the current request headers
|
||||||
|
@ -218,6 +218,13 @@ public class CookieManager extends CookieHandler
|
|||||||
// 'secure' cookies over unsecure links)
|
// 'secure' cookies over unsecure links)
|
||||||
if (pathMatches(path, cookie.getPath()) &&
|
if (pathMatches(path, cookie.getPath()) &&
|
||||||
(secureLink || !cookie.getSecure())) {
|
(secureLink || !cookie.getSecure())) {
|
||||||
|
// Enforce httponly attribute
|
||||||
|
if (cookie.isHttpOnly()) {
|
||||||
|
String s = uri.getScheme();
|
||||||
|
if (!"http".equalsIgnoreCase(s) && !"https".equalsIgnoreCase(s)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Let's check the authorize port list if it exists
|
// Let's check the authorize port list if it exists
|
||||||
String ports = cookie.getPortlist();
|
String ports = cookie.getPortlist();
|
||||||
if (ports != null && !ports.isEmpty()) {
|
if (ports != null && !ports.isEmpty()) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -297,6 +297,7 @@ class JarFile extends ZipFile {
|
|||||||
String name = names[i].toUpperCase(Locale.ENGLISH);
|
String name = names[i].toUpperCase(Locale.ENGLISH);
|
||||||
if (name.endsWith(".DSA") ||
|
if (name.endsWith(".DSA") ||
|
||||||
name.endsWith(".RSA") ||
|
name.endsWith(".RSA") ||
|
||||||
|
name.endsWith(".EC") ||
|
||||||
name.endsWith(".SF")) {
|
name.endsWith(".SF")) {
|
||||||
// Assume since we found a signature-related file
|
// Assume since we found a signature-related file
|
||||||
// that the jar is signed and that we therefore
|
// that the jar is signed and that we therefore
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -50,7 +50,7 @@ class JarVerifier {
|
|||||||
private Hashtable verifiedSigners;
|
private Hashtable verifiedSigners;
|
||||||
|
|
||||||
/* a table mapping names to code signers, for jar entries that have
|
/* a table mapping names to code signers, for jar entries that have
|
||||||
passed the .SF/.DSA -> MANIFEST check */
|
passed the .SF/.DSA/.EC -> MANIFEST check */
|
||||||
private Hashtable sigFileSigners;
|
private Hashtable sigFileSigners;
|
||||||
|
|
||||||
/* a hash table to hold .SF bytes */
|
/* a hash table to hold .SF bytes */
|
||||||
@ -111,7 +111,7 @@ class JarVerifier {
|
|||||||
/*
|
/*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
* 1. The manifest should be the first entry in the META-INF directory.
|
* 1. The manifest should be the first entry in the META-INF directory.
|
||||||
* 2. The .SF/.DSA files follow the manifest, before any normal entries
|
* 2. The .SF/.DSA/.EC files follow the manifest, before any normal entries
|
||||||
* 3. Any of the following will throw a SecurityException:
|
* 3. Any of the following will throw a SecurityException:
|
||||||
* a. digest mismatch between a manifest section and
|
* a. digest mismatch between a manifest section and
|
||||||
* the SF section.
|
* the SF section.
|
||||||
@ -129,7 +129,7 @@ class JarVerifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SignatureFileVerifier.isBlockOrSF(uname)) {
|
if (SignatureFileVerifier.isBlockOrSF(uname)) {
|
||||||
/* We parse only DSA or RSA PKCS7 blocks. */
|
/* We parse only DSA, RSA or EC PKCS7 blocks. */
|
||||||
parsingBlockOrSF = true;
|
parsingBlockOrSF = true;
|
||||||
baos.reset();
|
baos.reset();
|
||||||
mev.setEntry(null, je);
|
mev.setEntry(null, je);
|
||||||
|
@ -284,14 +284,16 @@ class DigestAuthentication extends AuthenticationInfo {
|
|||||||
params.setOpaque (p.findValue("opaque"));
|
params.setOpaque (p.findValue("opaque"));
|
||||||
params.setQop (p.findValue("qop"));
|
params.setQop (p.findValue("qop"));
|
||||||
|
|
||||||
String uri;
|
String uri="";
|
||||||
String method;
|
String method;
|
||||||
if (type == PROXY_AUTHENTICATION &&
|
if (type == PROXY_AUTHENTICATION &&
|
||||||
conn.tunnelState() == HttpURLConnection.TunnelState.SETUP) {
|
conn.tunnelState() == HttpURLConnection.TunnelState.SETUP) {
|
||||||
uri = HttpURLConnection.connectRequestURI(conn.getURL());
|
uri = HttpURLConnection.connectRequestURI(conn.getURL());
|
||||||
method = HTTP_CONNECT;
|
method = HTTP_CONNECT;
|
||||||
} else {
|
} else {
|
||||||
uri = conn.getRequestURI();
|
try {
|
||||||
|
uri = conn.getRequestURI();
|
||||||
|
} catch (IOException e) {}
|
||||||
method = conn.getMethod();
|
method = conn.getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1543,7 +1543,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||||||
* because ntlm does not support this feature.
|
* because ntlm does not support this feature.
|
||||||
*/
|
*/
|
||||||
private AuthenticationInfo
|
private AuthenticationInfo
|
||||||
resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) {
|
resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) throws IOException {
|
||||||
if ((proxyAuthentication != null )&&
|
if ((proxyAuthentication != null )&&
|
||||||
proxyAuthentication.getAuthScheme() != NTLM) {
|
proxyAuthentication.getAuthScheme() != NTLM) {
|
||||||
String raw = auth.raw();
|
String raw = auth.raw();
|
||||||
@ -1767,7 +1767,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||||||
/**
|
/**
|
||||||
* Sets pre-emptive proxy authentication in header
|
* Sets pre-emptive proxy authentication in header
|
||||||
*/
|
*/
|
||||||
private void setPreemptiveProxyAuthentication(MessageHeader requests) {
|
private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
|
||||||
AuthenticationInfo pauth
|
AuthenticationInfo pauth
|
||||||
= AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
|
= AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
|
||||||
http.getProxyPortUsed());
|
http.getProxyPortUsed());
|
||||||
@ -2123,13 +2123,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||||||
|
|
||||||
String requestURI = null;
|
String requestURI = null;
|
||||||
|
|
||||||
String getRequestURI() {
|
String getRequestURI() throws IOException {
|
||||||
if (requestURI == null) {
|
if (requestURI == null) {
|
||||||
try {
|
requestURI = http.getURLFile();
|
||||||
requestURI = http.getURLFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
requestURI = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return requestURI;
|
return requestURI;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -86,6 +86,9 @@ public class Providers {
|
|||||||
private static final String[] jarVerificationProviders = {
|
private static final String[] jarVerificationProviders = {
|
||||||
"sun.security.provider.Sun",
|
"sun.security.provider.Sun",
|
||||||
"sun.security.rsa.SunRsaSign",
|
"sun.security.rsa.SunRsaSign",
|
||||||
|
// Note: SunEC *is* in a signed JAR file, but it's not signed
|
||||||
|
// by EC itself. So it's still safe to be listed here.
|
||||||
|
"sun.security.ec.SunEC",
|
||||||
BACKUP_PROVIDER_CLASSNAME,
|
BACKUP_PROVIDER_CLASSNAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -286,8 +286,6 @@ public class SignerInfo implements DerEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String digestAlgname = getDigestAlgorithmId().getName();
|
String digestAlgname = getDigestAlgorithmId().getName();
|
||||||
if (digestAlgname.equalsIgnoreCase("SHA"))
|
|
||||||
digestAlgname = "SHA1";
|
|
||||||
|
|
||||||
byte[] dataSigned;
|
byte[] dataSigned;
|
||||||
|
|
||||||
@ -337,9 +335,12 @@ public class SignerInfo implements DerEncoder {
|
|||||||
String encryptionAlgname =
|
String encryptionAlgname =
|
||||||
getDigestEncryptionAlgorithmId().getName();
|
getDigestEncryptionAlgorithmId().getName();
|
||||||
|
|
||||||
if (encryptionAlgname.equalsIgnoreCase("SHA1withDSA"))
|
// Workaround: sometimes the encryptionAlgname is actually
|
||||||
encryptionAlgname = "DSA";
|
// a signature name
|
||||||
String algname = digestAlgname + "with" + encryptionAlgname;
|
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
|
||||||
|
if (tmp != null) encryptionAlgname = tmp;
|
||||||
|
String algname = AlgorithmId.makeSigAlg(
|
||||||
|
digestAlgname, encryptionAlgname);
|
||||||
|
|
||||||
Signature sig = Signature.getInstance(algname);
|
Signature sig = Signature.getInstance(algname);
|
||||||
X509Certificate cert = getCertificate(block);
|
X509Certificate cert = getCertificate(block);
|
||||||
|
@ -1031,9 +1031,9 @@ public class JarSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sigfile.length() > 8) {
|
if (sigfile.length() > 8) {
|
||||||
sigfile = sigfile.substring(0, 8).toUpperCase();
|
sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH);
|
||||||
} else {
|
} else {
|
||||||
sigfile = sigfile.toUpperCase();
|
sigfile = sigfile.toUpperCase(Locale.ENGLISH);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
|
StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
|
||||||
@ -1083,8 +1083,8 @@ public class JarSigner {
|
|||||||
ZipOutputStream zos = new ZipOutputStream(ps);
|
ZipOutputStream zos = new ZipOutputStream(ps);
|
||||||
|
|
||||||
/* First guess at what they might be - we don't xclude RSA ones. */
|
/* First guess at what they might be - we don't xclude RSA ones. */
|
||||||
String sfFilename = (META_INF + sigfile + ".SF").toUpperCase();
|
String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH);
|
||||||
String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase();
|
String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH);
|
||||||
|
|
||||||
Manifest manifest = new Manifest();
|
Manifest manifest = new Manifest();
|
||||||
Map<String,Attributes> mfEntries = manifest.getEntries();
|
Map<String,Attributes> mfEntries = manifest.getEntries();
|
||||||
@ -1447,9 +1447,10 @@ public class JarSigner {
|
|||||||
* . META-INF/*.SF
|
* . META-INF/*.SF
|
||||||
* . META-INF/*.DSA
|
* . META-INF/*.DSA
|
||||||
* . META-INF/*.RSA
|
* . META-INF/*.RSA
|
||||||
|
* . META-INF/*.EC
|
||||||
*/
|
*/
|
||||||
private boolean signatureRelated(String name) {
|
private boolean signatureRelated(String name) {
|
||||||
String ucName = name.toUpperCase();
|
String ucName = name.toUpperCase(Locale.ENGLISH);
|
||||||
if (ucName.equals(JarFile.MANIFEST_NAME) ||
|
if (ucName.equals(JarFile.MANIFEST_NAME) ||
|
||||||
ucName.equals(META_INF) ||
|
ucName.equals(META_INF) ||
|
||||||
(ucName.startsWith(SIG_PREFIX) &&
|
(ucName.startsWith(SIG_PREFIX) &&
|
||||||
@ -1459,7 +1460,7 @@ public class JarSigner {
|
|||||||
|
|
||||||
if (ucName.startsWith(META_INF) &&
|
if (ucName.startsWith(META_INF) &&
|
||||||
SignatureFileVerifier.isBlockOrSF(ucName)) {
|
SignatureFileVerifier.isBlockOrSF(ucName)) {
|
||||||
// .SF/.DSA/.RSA files in META-INF subdirs
|
// .SF/.DSA/.RSA/.EC files in META-INF subdirs
|
||||||
// are not considered signature-related
|
// are not considered signature-related
|
||||||
return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
|
return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
|
||||||
}
|
}
|
||||||
@ -2227,7 +2228,6 @@ class SignatureFile {
|
|||||||
}
|
}
|
||||||
BigInteger serial = certChain[0].getSerialNumber();
|
BigInteger serial = certChain[0].getSerialNumber();
|
||||||
|
|
||||||
String digestAlgorithm;
|
|
||||||
String signatureAlgorithm;
|
String signatureAlgorithm;
|
||||||
String keyAlgorithm = privateKey.getAlgorithm();
|
String keyAlgorithm = privateKey.getAlgorithm();
|
||||||
/*
|
/*
|
||||||
@ -2237,22 +2237,24 @@ class SignatureFile {
|
|||||||
if (sigalg == null) {
|
if (sigalg == null) {
|
||||||
|
|
||||||
if (keyAlgorithm.equalsIgnoreCase("DSA"))
|
if (keyAlgorithm.equalsIgnoreCase("DSA"))
|
||||||
digestAlgorithm = "SHA1";
|
signatureAlgorithm = "SHA1withDSA";
|
||||||
else if (keyAlgorithm.equalsIgnoreCase("RSA"))
|
else if (keyAlgorithm.equalsIgnoreCase("RSA"))
|
||||||
digestAlgorithm = "SHA256";
|
signatureAlgorithm = "SHA256withRSA";
|
||||||
else {
|
else if (keyAlgorithm.equalsIgnoreCase("EC"))
|
||||||
|
signatureAlgorithm = "SHA256withECDSA";
|
||||||
|
else
|
||||||
throw new RuntimeException("private key is not a DSA or "
|
throw new RuntimeException("private key is not a DSA or "
|
||||||
+ "RSA key");
|
+ "RSA key");
|
||||||
}
|
|
||||||
signatureAlgorithm = digestAlgorithm + "with" + keyAlgorithm;
|
|
||||||
} else {
|
} else {
|
||||||
signatureAlgorithm = sigalg;
|
signatureAlgorithm = sigalg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check common invalid key/signature algorithm combinations
|
// check common invalid key/signature algorithm combinations
|
||||||
String sigAlgUpperCase = signatureAlgorithm.toUpperCase();
|
String sigAlgUpperCase = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||||
if ((sigAlgUpperCase.endsWith("WITHRSA") &&
|
if ((sigAlgUpperCase.endsWith("WITHRSA") &&
|
||||||
!keyAlgorithm.equalsIgnoreCase("RSA")) ||
|
!keyAlgorithm.equalsIgnoreCase("RSA")) ||
|
||||||
|
(sigAlgUpperCase.endsWith("WITHECDSA") &&
|
||||||
|
!keyAlgorithm.equalsIgnoreCase("EC")) ||
|
||||||
(sigAlgUpperCase.endsWith("WITHDSA") &&
|
(sigAlgUpperCase.endsWith("WITHDSA") &&
|
||||||
!keyAlgorithm.equalsIgnoreCase("DSA"))) {
|
!keyAlgorithm.equalsIgnoreCase("DSA"))) {
|
||||||
throw new SignatureException
|
throw new SignatureException
|
||||||
|
@ -1407,7 +1407,7 @@ public final class KeyTool {
|
|||||||
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
|
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
|
||||||
return "SHA256WithRSA";
|
return "SHA256WithRSA";
|
||||||
} else if ("EC".equalsIgnoreCase(keyAlgName)) {
|
} else if ("EC".equalsIgnoreCase(keyAlgName)) {
|
||||||
return "SHA1withECDSA";
|
return "SHA256withECDSA";
|
||||||
} else {
|
} else {
|
||||||
throw new Exception(rb.getString
|
throw new Exception(rb.getString
|
||||||
("Cannot derive signature algorithm"));
|
("Cannot derive signature algorithm"));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright (c) 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -159,18 +159,10 @@ public final class TimestampedSigner extends ContentSigner {
|
|||||||
// "<digest>with<encryption>"
|
// "<digest>with<encryption>"
|
||||||
// or "<digest>with<encryption>and<mgf>"
|
// or "<digest>with<encryption>and<mgf>"
|
||||||
String signatureAlgorithm = parameters.getSignatureAlgorithm();
|
String signatureAlgorithm = parameters.getSignatureAlgorithm();
|
||||||
String digestAlgorithm = null;
|
String keyAlgorithm =
|
||||||
String keyAlgorithm = null;
|
AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
|
||||||
int with = signatureAlgorithm.indexOf("with");
|
String digestAlgorithm =
|
||||||
if (with > 0) {
|
AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
|
||||||
digestAlgorithm = signatureAlgorithm.substring(0, with);
|
|
||||||
int and = signatureAlgorithm.indexOf("and", with + 4);
|
|
||||||
if (and > 0) {
|
|
||||||
keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
|
|
||||||
} else {
|
|
||||||
keyAlgorithm = signatureAlgorithm.substring(with + 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
|
AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
|
||||||
|
|
||||||
// Examine signer's certificate
|
// Examine signer's certificate
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -54,14 +54,14 @@ public class SignatureFileVerifier {
|
|||||||
("-DIGEST-" + ManifestDigester.MF_MAIN_ATTRS).toUpperCase
|
("-DIGEST-" + ManifestDigester.MF_MAIN_ATTRS).toUpperCase
|
||||||
(Locale.ENGLISH);
|
(Locale.ENGLISH);
|
||||||
|
|
||||||
/** the PKCS7 block for this .DSA/.RSA file */
|
/** the PKCS7 block for this .DSA/.RSA/.EC file */
|
||||||
private PKCS7 block;
|
private PKCS7 block;
|
||||||
|
|
||||||
/** the raw bytes of the .SF file */
|
/** the raw bytes of the .SF file */
|
||||||
private byte sfBytes[];
|
private byte sfBytes[];
|
||||||
|
|
||||||
/** the name of the signature block file, uppercased and without
|
/** the name of the signature block file, uppercased and without
|
||||||
* the extension (.DSA/.RSA)
|
* the extension (.DSA/.RSA/.EC)
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ public class SignatureFileVerifier {
|
|||||||
/**
|
/**
|
||||||
* Create the named SignatureFileVerifier.
|
* Create the named SignatureFileVerifier.
|
||||||
*
|
*
|
||||||
* @param name the name of the signature block file (.DSA/.RSA)
|
* @param name the name of the signature block file (.DSA/.RSA/.EC)
|
||||||
*
|
*
|
||||||
* @param rawBytes the raw bytes of the signature block file
|
* @param rawBytes the raw bytes of the signature block file
|
||||||
*/
|
*/
|
||||||
@ -148,7 +148,8 @@ public class SignatureFileVerifier {
|
|||||||
*/
|
*/
|
||||||
public static boolean isBlockOrSF(String s) {
|
public static boolean isBlockOrSF(String s) {
|
||||||
// we currently only support DSA and RSA PKCS7 blocks
|
// we currently only support DSA and RSA PKCS7 blocks
|
||||||
if (s.endsWith(".SF") || s.endsWith(".DSA") || s.endsWith(".RSA")) {
|
if (s.endsWith(".SF") || s.endsWith(".DSA") ||
|
||||||
|
s.endsWith(".RSA") || s.endsWith(".EC")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -883,4 +883,53 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
|||||||
nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede");
|
nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede");
|
||||||
nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40");
|
nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a signature algorithm name from a digest algorithm
|
||||||
|
* name and a encryption algorithm name.
|
||||||
|
*/
|
||||||
|
public static String makeSigAlg(String digAlg, String encAlg) {
|
||||||
|
digAlg = digAlg.replace("-", "").toUpperCase(Locale.ENGLISH);
|
||||||
|
if (digAlg.equalsIgnoreCase("SHA")) digAlg = "SHA1";
|
||||||
|
|
||||||
|
encAlg = encAlg.toUpperCase(Locale.ENGLISH);
|
||||||
|
if (encAlg.equals("EC")) encAlg = "ECDSA";
|
||||||
|
|
||||||
|
return digAlg + "with" + encAlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the encryption algorithm name from a signature
|
||||||
|
* algorithm name.
|
||||||
|
*/
|
||||||
|
public static String getEncAlgFromSigAlg(String signatureAlgorithm) {
|
||||||
|
signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||||
|
int with = signatureAlgorithm.indexOf("WITH");
|
||||||
|
String keyAlgorithm = null;
|
||||||
|
if (with > 0) {
|
||||||
|
int and = signatureAlgorithm.indexOf("AND", with + 4);
|
||||||
|
if (and > 0) {
|
||||||
|
keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
|
||||||
|
} else {
|
||||||
|
keyAlgorithm = signatureAlgorithm.substring(with + 4);
|
||||||
|
}
|
||||||
|
if (keyAlgorithm.equalsIgnoreCase("ECDSA")) {
|
||||||
|
keyAlgorithm = "EC";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the digest algorithm name from a signature
|
||||||
|
* algorithm name.
|
||||||
|
*/
|
||||||
|
public static String getDigAlgFromSigAlg(String signatureAlgorithm) {
|
||||||
|
signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
|
||||||
|
int with = signatureAlgorithm.indexOf("WITH");
|
||||||
|
if (with > 0) {
|
||||||
|
return signatureAlgorithm.substring(0, with);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -34,6 +34,7 @@ import sun.misc.BASE64Encoder;
|
|||||||
import sun.misc.BASE64Decoder;
|
import sun.misc.BASE64Decoder;
|
||||||
|
|
||||||
import sun.security.pkcs.*;
|
import sun.security.pkcs.*;
|
||||||
|
import sun.security.x509.AlgorithmId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>A signature file as defined in the <a
|
* <p>A signature file as defined in the <a
|
||||||
@ -103,7 +104,7 @@ public class SignatureFile {
|
|||||||
if (name.length() > 8 || name.indexOf('.') != -1) {
|
if (name.length() > 8 || name.indexOf('.') != -1) {
|
||||||
throw new JarException("invalid file name");
|
throw new JarException("invalid file name");
|
||||||
}
|
}
|
||||||
rawName = name.toUpperCase();
|
rawName = name.toUpperCase(Locale.ENGLISH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +218,8 @@ public class SignatureFile {
|
|||||||
if (signatureBlock != null) {
|
if (signatureBlock != null) {
|
||||||
SignerInfo info = signatureBlock.getSignerInfos()[0];
|
SignerInfo info = signatureBlock.getSignerInfos()[0];
|
||||||
suffix = info.getDigestEncryptionAlgorithmId().getName();
|
suffix = info.getDigestEncryptionAlgorithmId().getName();
|
||||||
suffix = suffix.substring(suffix.length() - 3);
|
String temp = AlgorithmId.getEncAlgFromSigAlg(suffix);
|
||||||
|
if (temp != null) suffix = temp;
|
||||||
}
|
}
|
||||||
return "META-INF/" + rawName + "." + suffix;
|
return "META-INF/" + rawName + "." + suffix;
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ EOF
|
|||||||
#The alternative would be to use /usr/bin/pargs [pid] to get
|
#The alternative would be to use /usr/bin/pargs [pid] to get
|
||||||
#all the args for a process, splice them back into one
|
#all the args for a process, splice them back into one
|
||||||
#long string, then grep.
|
#long string, then grep.
|
||||||
UU=`/usr/bin/id -un`
|
UU=`/usr/xpg4/bin/id -u -n`
|
||||||
psCmd="pgrep -f -l -U $UU"
|
psCmd="pgrep -f -l -U $UU"
|
||||||
else
|
else
|
||||||
ulimit -c 0
|
ulimit -c 0
|
||||||
|
48
jdk/test/java/math/BigInteger/ExtremeShiftingTests.java
Normal file
48
jdk/test/java/math/BigInteger/ExtremeShiftingTests.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 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 6371401
|
||||||
|
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
|
||||||
|
* @author Joseph D. Darcy
|
||||||
|
*/
|
||||||
|
import static java.math.BigInteger.*;
|
||||||
|
|
||||||
|
public class ExtremeShiftingTests {
|
||||||
|
public static void main(String... args) {
|
||||||
|
try {
|
||||||
|
ONE.shiftLeft(Integer.MIN_VALUE);
|
||||||
|
throw new RuntimeException("Should not reach here.");
|
||||||
|
} catch (ArithmeticException ae) {
|
||||||
|
; // Expected
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ONE.shiftRight(Integer.MIN_VALUE);
|
||||||
|
throw new RuntimeException("Should not reach here.");
|
||||||
|
} catch (ArithmeticException ae) {
|
||||||
|
; // Expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 6644726
|
* @bug 6644726 6873543
|
||||||
* @summary Cookie management issues
|
* @summary Cookie management issues
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -170,6 +170,28 @@ public class B6644726 {
|
|||||||
if (isIn(clst, "myCookie8=")) {
|
if (isIn(clst, "myCookie8=")) {
|
||||||
fail("A cookie with an invalid port list was returned");
|
fail("A cookie with an invalid port list was returned");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test httpOnly flag (CR# 6873543)
|
||||||
|
lst.clear();
|
||||||
|
map.clear();
|
||||||
|
cm.getCookieStore().removeAll();
|
||||||
|
lst.add("myCookie11=httpOnlyTest; httpOnly");
|
||||||
|
map.put("Set-Cookie", lst);
|
||||||
|
uri = new URI("http://www.sun.com/");
|
||||||
|
cm.put(uri, map);
|
||||||
|
m = cm.get(uri, emptyMap);
|
||||||
|
clst = m.get("Cookie");
|
||||||
|
// URI scheme was http: so we should get the cookie
|
||||||
|
if (!isIn(clst, "myCookie11=")) {
|
||||||
|
fail("Missing cookie with httpOnly flag");
|
||||||
|
}
|
||||||
|
uri = new URI("javascript://www.sun.com/");
|
||||||
|
m = cm.get(uri, emptyMap);
|
||||||
|
clst = m.get("Cookie");
|
||||||
|
// URI scheme was neither http or https so we shouldn't get the cookie
|
||||||
|
if (isIn(clst, "myCookie11=")) {
|
||||||
|
fail("Should get the cookie with httpOnly when scheme is javascript:");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isIn(List<String> lst, String cookie) {
|
private static boolean isIn(List<String> lst, String cookie) {
|
||||||
|
68
jdk/test/sun/net/www/protocol/http/B6890349.java
Normal file
68
jdk/test/sun/net/www/protocol/http/B6890349.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 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 6890349
|
||||||
|
* @run main/othervm B6890349
|
||||||
|
* @summary Light weight HTTP server
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class B6890349 extends Thread {
|
||||||
|
public static final void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ServerSocket server = new ServerSocket (0);
|
||||||
|
int port = server.getLocalPort();
|
||||||
|
System.out.println ("listening on " + port);
|
||||||
|
B6890349 t = new B6890349 (server);
|
||||||
|
t.start();
|
||||||
|
URL u = new URL ("http://127.0.0.1:"+port+"/foo\nbar");
|
||||||
|
HttpURLConnection urlc = (HttpURLConnection)u.openConnection ();
|
||||||
|
InputStream is = urlc.getInputStream();
|
||||||
|
throw new RuntimeException ("Test failed");
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println ("OK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSocket server;
|
||||||
|
|
||||||
|
B6890349 (ServerSocket server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
String resp = "HTTP/1.1 200 Ok\r\nContent-length: 0\r\n\r\n";
|
||||||
|
|
||||||
|
public void run () {
|
||||||
|
try {
|
||||||
|
Socket s = server.accept ();
|
||||||
|
OutputStream os = s.getOutputStream();
|
||||||
|
os.write (resp.getBytes());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
jdk/test/sun/security/tools/jarsigner/ec.sh
Normal file
73
jdk/test/sun/security/tools/jarsigner/ec.sh
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2009 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 6870812
|
||||||
|
# @summary enhance security tools to use ECC algorithm
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ "${TESTJAVA}" = "" ] ; then
|
||||||
|
JAVAC_CMD=`which javac`
|
||||||
|
TESTJAVA=`dirname $JAVAC_CMD`/..
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set platform-dependent variables
|
||||||
|
OS=`uname -s`
|
||||||
|
case "$OS" in
|
||||||
|
Windows_* )
|
||||||
|
FS="\\"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
FS="/"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
KS=ec.jks
|
||||||
|
JFILE=ec.jar
|
||||||
|
|
||||||
|
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
|
||||||
|
JAR=$TESTJAVA${FS}bin${FS}jar
|
||||||
|
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
|
||||||
|
|
||||||
|
rm $KS $JFILE
|
||||||
|
echo A > A
|
||||||
|
$JAR cvf $JFILE A
|
||||||
|
|
||||||
|
$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11
|
||||||
|
$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12
|
||||||
|
$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 || exit 13
|
||||||
|
$KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14
|
||||||
|
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit $JFILE c -debug -strict -sigalg SHA512withECDSA || exit 23
|
||||||
|
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict || exit 31
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE b -debug -strict || exit 32
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE c -debug -strict || exit 33
|
||||||
|
|
||||||
|
# Not signed by x, should exit with non-zero
|
||||||
|
$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE x -debug -strict && exit 34
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user