Reviewed-by: dfuchs
This commit is contained in:
Jaikiran Pai 2026-04-22 11:28:56 +00:00
commit c796ed1ad8
30 changed files with 438 additions and 267 deletions

View File

@ -7708,10 +7708,11 @@ instruct bytes_reverse_unsigned_short(iRegINoSp dst, iRegIorL2I src) %{
match(Set dst (ReverseBytesUS src));
ins_cost(INSN_COST);
format %{ "rev16w $dst, $src" %}
format %{ "rev16w $dst, $src\t# $dst -> unsigned short" %}
ins_encode %{
__ rev16w(as_Register($dst$$reg), as_Register($src$$reg));
__ narrow_subword_type(as_Register($dst$$reg), T_CHAR);
%}
ins_pipe(ialu_reg);

View File

@ -2815,6 +2815,17 @@ void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in
}
}
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
assert(is_subword_type(bt), "required");
switch (bt) {
case T_BOOLEAN: andw(reg, reg, 1); break;
case T_BYTE: sxtbw(reg, reg); break;
case T_CHAR: uxthw(reg, reg); break;
case T_SHORT: sxthw(reg, reg); break;
default: ShouldNotReachHere();
}
}
void MacroAssembler::decrementw(Register reg, int value)
{
if (value < 0) { incrementw(reg, -value); return; }

View File

@ -33,6 +33,7 @@
#include "oops/compressedOops.hpp"
#include "oops/compressedKlass.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
class OopMap;
@ -719,6 +720,9 @@ public:
// Support for sign-extension (hi:lo = extend_sign(lo))
void extend_sign(Register hi, Register lo);
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
void narrow_subword_type(Register reg, BasicType bt);
// Load and store values by size and signed-ness
void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed);
void store_sized_value(Address dst, Register src, size_t size_in_bytes);

View File

@ -9214,10 +9214,12 @@ instruct bytes_reverse_long(iRegL dst, iRegL src) %{
instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
match(Set dst (ReverseBytesUS src));
size(4);
format %{ "REV16 $dst,$src" %}
size(8);
format %{ "REV32 $dst,$src\n\t"
"LSR $dst,$dst,#16" %}
ins_encode %{
__ rev16($dst$$Register, $src$$Register);
__ rev($dst$$Register, $src$$Register);
__ mov($dst$$Register, AsmOperand($dst$$Register, lsr, 16));
%}
ins_pipe( iload_mem ); // FIXME
%}

View File

@ -12480,6 +12480,19 @@ instruct countTrailingZerosL_cnttzd(iRegIdst dst, iRegLsrc src) %{
ins_pipe(pipe_class_default);
%}
// Expand nodes for byte_reverse_int/ushort/short.
instruct rlwinm(iRegIdst dst, iRegIsrc src, immI16 shift, immI16 mb, immI16 me) %{
effect(DEF dst, USE src, USE shift, USE mb, USE me);
predicate(false);
format %{ "RLWINM $dst, $src, $shift, $mb, $me" %}
size(4);
ins_encode %{
__ rlwinm($dst$$Register, $src$$Register, $shift$$constant, $mb$$constant, $me$$constant);
%}
ins_pipe(pipe_class_default);
%}
// Expand nodes for byte_reverse_int.
instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{
effect(DEF dst, USE src, USE n, USE b);
@ -12636,34 +12649,22 @@ instruct bytes_reverse_long(iRegLdst dst, iRegLsrc src) %{
ins_pipe(pipe_class_default);
%}
// Need zero extend. Must not use brh only.
instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{
match(Set dst (ReverseBytesUS src));
predicate(!UseByteReverseInstructions);
ins_cost(2*DEFAULT_COST);
expand %{
immI16 imm31 %{ (int) 31 %}
immI16 imm24 %{ (int) 24 %}
immI16 imm16 %{ (int) 16 %}
immI16 imm8 %{ (int) 8 %}
urShiftI_reg_imm(dst, src, imm8);
rlwinm(dst, src, imm24, imm24, imm31);
insrwi(dst, src, imm8, imm16);
%}
%}
instruct bytes_reverse_ushort(iRegIdst dst, iRegIsrc src) %{
match(Set dst (ReverseBytesUS src));
predicate(UseByteReverseInstructions);
ins_cost(DEFAULT_COST);
size(4);
format %{ "BRH $dst, $src" %}
ins_encode %{
__ brh($dst$$Register, $src$$Register);
%}
ins_pipe(pipe_class_default);
%}
instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{
match(Set dst (ReverseBytesS src));
predicate(!UseByteReverseInstructions);

View File

@ -55,6 +55,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#ifdef PRODUCT
@ -2540,6 +2541,17 @@ void MacroAssembler::sign_extend_short(Register reg) {
movswl(reg, reg); // movsxw
}
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
assert(is_subword_type(bt), "required");
switch (bt) {
case T_BOOLEAN: andl(reg, 1); break;
case T_BYTE: movsbl(reg, reg); break;
case T_CHAR: movzwl(reg, reg); break;
case T_SHORT: movswl(reg, reg); break;
default: ShouldNotReachHere();
}
}
void MacroAssembler::testl(Address dst, int32_t imm32) {
if (imm32 >= 0 && is8bit(imm32)) {
testb(dst, imm32);

View File

@ -444,6 +444,9 @@ class MacroAssembler: public Assembler {
void sign_extend_short(Register reg);
void sign_extend_byte(Register reg);
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
void narrow_subword_type(Register reg, BasicType bt);
// Division by power of 2, rounding towards 0
void division_with_shift(Register reg, int shift_value);

View File

@ -10899,10 +10899,11 @@ instruct xaddB(memory mem, rRegI newval, rFlagsReg cr) %{
predicate(!n->as_LoadStore()->result_not_used());
match(Set newval (GetAndAddB mem newval));
effect(KILL cr);
format %{ "xaddb_lock $mem, $newval" %}
format %{ "xaddb_lock $mem, $newval\t# $newval -> byte" %}
ins_encode %{
__ lock();
__ xaddb($mem$$Address, $newval$$Register);
__ narrow_subword_type($newval$$Register, T_BYTE);
%}
ins_pipe(pipe_cmpxchg);
%}
@ -10935,10 +10936,11 @@ instruct xaddS(memory mem, rRegI newval, rFlagsReg cr) %{
predicate(!n->as_LoadStore()->result_not_used());
match(Set newval (GetAndAddS mem newval));
effect(KILL cr);
format %{ "xaddw_lock $mem, $newval" %}
format %{ "xaddw_lock $mem, $newval\t# $newval -> short" %}
ins_encode %{
__ lock();
__ xaddw($mem$$Address, $newval$$Register);
__ narrow_subword_type($newval$$Register, T_SHORT);
%}
ins_pipe(pipe_cmpxchg);
%}
@ -11017,18 +11019,20 @@ instruct xaddL(memory mem, rRegL newval, rFlagsReg cr) %{
instruct xchgB( memory mem, rRegI newval) %{
match(Set newval (GetAndSetB mem newval));
format %{ "XCHGB $newval,[$mem]" %}
format %{ "XCHGB $newval,[$mem]\t# $newval -> byte" %}
ins_encode %{
__ xchgb($newval$$Register, $mem$$Address);
__ narrow_subword_type($newval$$Register, T_BYTE);
%}
ins_pipe( pipe_cmpxchg );
%}
instruct xchgS( memory mem, rRegI newval) %{
match(Set newval (GetAndSetS mem newval));
format %{ "XCHGW $newval,[$mem]" %}
format %{ "XCHGW $newval,[$mem]\t# $newval -> short" %}
ins_encode %{
__ xchgw($newval$$Register, $mem$$Address);
__ narrow_subword_type($newval$$Register, T_SHORT);
%}
ins_pipe( pipe_cmpxchg );
%}
@ -25317,6 +25321,7 @@ instruct reinterpretHF2S(rRegI dst, regF src)
format %{ "evmovw $dst, $src" %}
ins_encode %{
__ evmovw($dst$$Register, $src$$XMMRegister);
__ narrow_subword_type($dst$$Register, T_SHORT);
%}
ins_pipe(pipe_slow);
%}

View File

@ -707,6 +707,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current,
if (zip != nullptr && error_msg == nullptr) {
new_entry = new ClassPathZipEntry(zip, path);
} else {
log_info(class, path)("failed: %s, err: %s", path, error_msg);
return nullptr;
}
log_info(class, path)("opened: %s", path);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. 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
@ -47,7 +47,38 @@ final class PBES1Core {
private final MessageDigest md;
private final String algo;
private byte[] salt = null;
private int iCount = 10;
// RFC 8018 and NIST SP 800-132 sec 5.2 recommend 1000 as the minimum
private int iCount = PKCS12PBECipherCore.DEFAULT_COUNT;
// utility method for checking weak salts of PBEWithMD5AndTripleDES cipher
private static boolean isWeak(byte[] s) {
// consider salts weak if it met both of the following conditions:
// 1) s[0...3] == s[4...7]
// 2) s[0] == s[3] && s[1] == s[2]
if (Arrays.equals(s, 0, 4, s, 4, 8)) {
return (s[0] == s[3]) && (s[1] == s[2]);
}
return false;
}
// utility method for generating 8-byte salts
private static byte[] generateSalt(String algo, SecureRandom sr) {
byte[] salt = new byte[8];
sr.nextBytes(salt);
// check and re-generate for DESede if necessary
if (algo.equals("DESede")) {
// prevent an infinite-loop in case of a rigged SecureRandom
int numAttempts = 50;
while (isWeak(salt)) {
sr.nextBytes(salt);
if (numAttempts-- < 0) {
throw new ProviderException(
"Unable to find salts after 50 attempts");
}
}
}
return salt;
}
/**
* Creates an instance of PBE Cipher using the specified CipherSpi
@ -163,8 +194,7 @@ final class PBES1Core {
AlgorithmParameters getParameters() {
AlgorithmParameters params;
if (salt == null) {
salt = new byte[8];
SunJCE.getRandom().nextBytes(salt);
salt = generateSalt(algo, SunJCE.getRandom());
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
try {
@ -227,8 +257,7 @@ final class PBES1Core {
if (params == null) {
// create random salt and use default iteration count
salt = new byte[8];
random.nextBytes(salt);
salt = generateSalt(algo, random);
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
@ -240,6 +269,15 @@ final class PBES1Core {
throw new InvalidAlgorithmParameterException
("Salt must be 8 bytes long");
}
// for DESede, reject weak salts for encryption
if (algo.equals("DESede") &&
(opmode == Cipher.ENCRYPT_MODE ||
opmode == Cipher.WRAP_MODE) &&
isWeak(salt)) {
throw new InvalidAlgorithmParameterException(
"Weak salts cannot be used for encryption");
}
iCount = ((PBEParameterSpec) params).getIterationCount();
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. 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
@ -53,7 +53,7 @@ final class PKCS12PBECipherCore {
private int iCount = 0;
private static final int DEFAULT_SALT_LENGTH = 20;
private static final int DEFAULT_COUNT = 1024;
static final int DEFAULT_COUNT = 1024;
static final int CIPHER_KEY = 1;
static final int CIPHER_IV = 2;

View File

@ -190,15 +190,16 @@ public class SegmentFactories {
if (VM.isDirectMemoryPageAligned()) {
byteAlignment = Math.max(byteAlignment, AbstractMemorySegmentImpl.NIO_ACCESS.pageSize());
}
// Always allocate at least some memory so that zero-length segments have distinct
// non-zero addresses.
byteSize = Math.max(1, byteSize);
// Align the allocation size up to a multiple of 8 so we can init the memory with longs
long alignedSize = init ? Utils.alignUp(byteSize, Long.BYTES) : byteSize;
// Check for wrap around
if (alignedSize < 0) {
throw new OutOfMemoryError();
}
// Always allocate at least some memory so that zero-length segments have distinct
// non-zero addresses.
alignedSize = Math.max(1, alignedSize);
long allocationSize;
long allocationBase;
@ -226,12 +227,13 @@ public class SegmentFactories {
if (init) {
initNativeMemory(result, alignedSize);
}
final long cleanupByteSize = byteSize;
sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() {
@Override
public void cleanup() {
UNSAFE.freeMemory(allocationBase);
if (shouldReserve) {
AbstractMemorySegmentImpl.NIO_ACCESS.unreserveMemory(allocationSize, byteSize);
AbstractMemorySegmentImpl.NIO_ACCESS.unreserveMemory(allocationSize, cleanupByteSize);
}
}
});

View File

@ -66,6 +66,7 @@ public class X509Factory extends CertificateFactorySpi {
public static final String END_CERT = "-----END CERTIFICATE-----";
private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX
public static final int BER_ITERATION_COUNT = 128; // Limit nested depth
private static final Cache<Object, X509CertImpl> certCache
= Cache.newSoftMemoryCache(750);
@ -570,7 +571,7 @@ public class X509Factory extends CertificateFactorySpi {
if (c == DerValue.tag_Sequence) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(2048);
bout.write(c);
readBERInternal(is, bout, c);
readBERInternal(is, bout, c, BER_ITERATION_COUNT);
return bout.toByteArray();
} else {
try {
@ -594,12 +595,16 @@ public class X509Factory extends CertificateFactorySpi {
* @param is Read from this InputStream
* @param bout Write into this OutputStream
* @param tag Tag already read (-1 mean not read)
* @param depth nesting depth limit
* @return The current tag, used to check EOC in indefinite-length BER
* @throws IOException Any parsing error
*/
private static int readBERInternal(InputStream is,
ByteArrayOutputStream bout, int tag) throws IOException {
ByteArrayOutputStream bout, int tag, int depth) throws IOException {
if (depth-- == 0) {
throw new IOException("Nesting sequence depth limit reached.");
}
if (tag == -1) { // Not read before the call, read now
tag = is.read();
if (tag == -1) {
@ -625,7 +630,7 @@ public class X509Factory extends CertificateFactorySpi {
"Non constructed encoding must have definite length");
}
while (true) {
int subTag = readBERInternal(is, bout, -1);
int subTag = readBERInternal(is, bout, -1, depth);
if (subTag == 0) { // EOC, end of indefinite-length section
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. 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
@ -43,9 +43,7 @@ import static sun.security.x509.PKIXExtensions.IssuingDistributionPoint_Id;
/**
* Class to obtain CRLs via the CRLDistributionPoints extension.
* Note that the functionality of this class must be explicitly enabled
* via a system property, see the USE_CRLDP variable below.
*
* <p>
* This class uses the URICertStore class to fetch CRLs. The URICertStore
* class also implements CRL caching: see the class description for more
* information.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. 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
@ -1007,13 +1007,17 @@ class RevocationChecker extends PKIXRevocationChecker {
// any way to convey them back to the application.
// That's the default, so no need to write code.
builderParams.setDate(params.date());
builderParams.setCertPathCheckers(params.certPathCheckers());
builderParams.setSigProvider(params.sigProvider());
// Skip revocation during this build to detect circular
// references. But check revocation afterwards, using the
// key (or any other that works).
builderParams.setRevocationEnabled(false);
// Remove itself from params to avoid circular reference.
builderParams.setCertPathCheckers(params.certPathCheckers()
.stream()
.filter(checker -> checker != this)
.toList());
// check for AuthorityInformationAccess extension
if (Builder.USE_AIA) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2026, Oracle and/or its affiliates. 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
@ -568,7 +568,7 @@ static jlong
readCEN(jzfile *zip, jint knownTotal)
{
/* Following are unsigned 32-bit */
jlong endpos, end64pos, cenpos, cenlen, cenoff;
jlong endpos, end64pos, cenpos, cenlen, cenoff, total64;
/* Following are unsigned 16-bit */
jint total, tablelen, i, j;
unsigned char *cenbuf = NULL;
@ -604,7 +604,16 @@ readCEN(jzfile *zip, jint knownTotal)
if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
cenlen = ZIP64_ENDSIZ(end64buf);
cenoff = ZIP64_ENDOFF(end64buf);
total = (jint)ZIP64_ENDTOT(end64buf);
total64 = ZIP64_ENDTOT(end64buf);
/* ZIP64 size, offset and total-count fields are unsigned 64-bit
* values. Sizes and offsets that do not fit in signed jlong
* (i.e., >= 2^63), or total values that do not fit in jint, are
* not supported and indicate a corrupt or invalid zip file.
*/
if (cenlen < 0 || cenoff < 0 || total64 < 0 || total64 > INT_MAX) {
ZIP_FORMAT_ERROR("Zip64 END values exceed supported size");
}
total = (jint)total64;
endpos = end64pos;
#ifdef USE_MMAP
endhdrlen = ZIP64_ENDHDR;
@ -1137,20 +1146,8 @@ ZIP_FreeEntry(jzfile *jz, jzentry *ze)
}
}
/*
* Returns the zip entry corresponding to the specified name, or
* NULL if not found.
*/
jzentry *
ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
{
if (ulen == 0) {
return ZIP_GetEntry2(zip, name, (jint)strlen(name), JNI_FALSE);
}
return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE);
}
jboolean equals(char* name1, int len1, char* name2, int len2) {
static jboolean
equals(const char* name1, int len1, const char* name2, int len2) {
if (len1 != len2) {
return JNI_FALSE;
}
@ -1162,16 +1159,12 @@ jboolean equals(char* name1, int len1, char* name2, int len2) {
return JNI_TRUE;
}
/*
* Returns the zip entry corresponding to the specified name, or
* NULL if not found.
* This method supports embedded null character in "name", use ulen
* for the length of "name".
*/
jzentry *
ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
ZIP_GetEntry(jzfile *zip, const char *name)
{
unsigned int hsh = hashN(name, ulen);
// length of the entry name being searched for
const jint name_len = (jint) strlen(name);
const unsigned int hsh = hashN(name, name_len);
jint idx;
jzentry *ze = 0;
@ -1182,79 +1175,47 @@ ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
idx = zip->table[hsh % zip->tablelen];
/*
* This while loop is an optimization where a double lookup
* for name and name+/ is being performed. The name char
* array has enough room at the end to try again with a
* slash appended if the first table lookup does not succeed.
*/
while(1) {
/* Check the cached entry first */
ze = zip->cache;
if (ze && equals(ze->name, ze->nlen, name, ulen)) {
/* Cache hit! Remove and return the cached entry. */
zip->cache = 0;
ZIP_Unlock(zip);
return ze;
}
ze = 0;
/*
* Search down the target hash chain for a cell whose
* 32 bit hash matches the hashed name.
*/
while (idx != ZIP_ENDCHAIN) {
jzcell *zc = &zip->entries[idx];
if (zc->hash == hsh) {
/*
* OK, we've found a ZIP entry whose 32 bit hashcode
* matches the name we're looking for. Try to read
* its entry information from the CEN. If the CEN
* name matches the name we're looking for, we're
* done.
* If the names don't match (which should be very rare)
* we keep searching.
*/
ze = newEntry(zip, zc, ACCESS_RANDOM);
if (ze && equals(ze->name, ze->nlen, name, ulen)) {
break;
}
if (ze != 0) {
/* We need to release the lock across the free call */
ZIP_Unlock(zip);
ZIP_FreeEntry(zip, ze);
ZIP_Lock(zip);
}
ze = 0;
}
idx = zc->next;
}
/* Entry found, return it */
if (ze != 0) {
break;
}
/* If no need to try appending slash, we are done */
if (!addSlash) {
break;
}
/* Slash is already there? */
if (ulen > 0 && name[ulen - 1] == '/') {
break;
}
/* Add slash and try once more */
name[ulen++] = '/';
name[ulen] = '\0';
hsh = hash_append(hsh, '/');
idx = zip->table[hsh % zip->tablelen];
addSlash = JNI_FALSE;
/* Check the cached entry first */
ze = zip->cache;
if (ze && equals(ze->name, ze->nlen, name, name_len)) {
/* Cache hit! Remove and return the cached entry. */
zip->cache = 0;
ZIP_Unlock(zip);
return ze;
}
ze = 0;
/*
* Search down the target hash chain for a cell whose
* 32 bit hash matches the hashed name.
*/
while (idx != ZIP_ENDCHAIN) {
jzcell *zc = &zip->entries[idx];
if (zc->hash == hsh) {
/*
* OK, we've found a ZIP entry whose 32 bit hashcode
* matches the name we're looking for. Try to read
* its entry information from the CEN. If the CEN
* name matches the name we're looking for, we're
* done.
* If the names don't match (which should be very rare)
* we keep searching.
*/
ze = newEntry(zip, zc, ACCESS_RANDOM);
if (ze && equals(ze->name, ze->nlen, name, name_len)) {
break;
}
if (ze != 0) {
/* We need to release the lock across the free call */
ZIP_Unlock(zip);
ZIP_FreeEntry(zip, ze);
ZIP_Lock(zip);
}
ze = 0;
}
idx = zc->next;
}
Finally:
ZIP_Unlock(zip);
return ze;
@ -1466,9 +1427,9 @@ InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
* has the size bigger than 2**32 bytes in ONE invocation.
*/
JNIEXPORT jzentry *
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
ZIP_FindEntry(jzfile *zip, const char *name, jint *sizeP, jint *nameLenP)
{
jzentry *entry = ZIP_GetEntry(zip, name, 0);
jzentry *entry = ZIP_GetEntry(zip, name);
if (entry) {
*sizeP = (jint)entry->size;
*nameLenP = (jint)strlen(entry->name);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2026, Oracle and/or its affiliates. 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
@ -241,8 +241,15 @@ typedef struct jzfile { /* Zip file */
*/
#define ZIP_ENDCHAIN ((jint)-1)
/*
* Returns the ZIP entry corresponding to the given (NULL terminated)
* entry name. Returns NULL if no entry is found by that name.
* If the entry is found, then the value of the given sizeP will be
* updated to the ZIP entry's size and the value of nameLenP will be
* updated to the ZIP entry name's length.
*/
JNIEXPORT jzentry *
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP);
ZIP_FindEntry(jzfile *zip, const char *name, jint *sizeP, jint *nameLenP);
JNIEXPORT jboolean
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm);
@ -268,8 +275,12 @@ ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
JNIEXPORT void
ZIP_Close(jzfile *zip);
/*
* Returns the ZIP entry corresponding to the given (NULL terminated)
* entry name. Returns NULL if no entry is found by that name.
*/
jzentry *
ZIP_GetEntry(jzfile *zip, char *name, jint ulen);
ZIP_GetEntry(jzfile *zip, const char *name);
void
ZIP_Lock(jzfile *zip);
void
@ -279,7 +290,6 @@ ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len);
JNIEXPORT void
ZIP_FreeEntry(jzfile *zip, jzentry *ze);
jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash);
JNIEXPORT jboolean
ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. 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
@ -146,6 +146,8 @@ public abstract class AreaOp {
public static final int RSTAG_INSIDE = 1;
public static final int RSTAG_OUTSIDE = -1;
public static final int MAX_LINK_COUNT = 1024;
public abstract void newRow();
public abstract int classify(Edge e);
@ -195,6 +197,25 @@ public abstract class AreaOp {
}
};
private void consumeSubCurves(Vector<CurveLink> subcurves,
Vector<ChainEnd> chains,
Vector<Curve> curve) {
finalizeSubCurves(subcurves, chains);
Enumeration<CurveLink> enum_ = subcurves.elements();
while (enum_.hasMoreElements()) {
CurveLink link = enum_.nextElement();
curve.add(link.getMoveto());
CurveLink nextlink = link;
while ((nextlink = nextlink.getNext()) != null) {
if (!link.absorb(nextlink)) {
curve.add(link.getSubCurve());
link = nextlink;
}
}
curve.add(link.getSubCurve());
}
}
private Vector<Curve> pruneEdges(Vector<Edge> edges) {
int numedges = edges.size();
if (numedges < 2) {
@ -218,6 +239,8 @@ public abstract class AreaOp {
Vector<CurveLink> subcurves = new Vector<>();
Vector<ChainEnd> chains = new Vector<>();
Vector<CurveLink> links = new Vector<>();
Vector<Curve> ret = new Vector<>();
int linkCount = 0;
// Active edges are between left (inclusive) and right (exclusive)
while (left < numedges) {
double y = yrange[0];
@ -390,27 +413,22 @@ public abstract class AreaOp {
System.out.println(" "+link.getSubCurve());
}
}
// If we have complex area calculation, we should consume the
// intermediate subcurves to optimize memory footprint
if (linkCount >= MAX_LINK_COUNT) {
consumeSubCurves(subcurves, chains, ret);
linkCount = 0;
chains.clear();
subcurves.clear();
}
linkCount += links.size();
resolveLinks(subcurves, chains, links);
links.clear();
// Finally capture the bottom of the valid Y range as the top
// of the next Y range.
yrange[0] = yend;
}
finalizeSubCurves(subcurves, chains);
Vector<Curve> ret = new Vector<>();
Enumeration<CurveLink> enum_ = subcurves.elements();
while (enum_.hasMoreElements()) {
CurveLink link = enum_.nextElement();
ret.add(link.getMoveto());
CurveLink nextlink = link;
while ((nextlink = nextlink.getNext()) != null) {
if (!link.absorb(nextlink)) {
ret.add(link.getSubCurve());
link = nextlink;
}
}
ret.add(link.getSubCurve());
}
consumeSubCurves(subcurves, chains, ret);
return ret;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. 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
@ -1046,6 +1046,9 @@ public abstract class Curve {
double bump = ymin;
double maxbump = Math.min(ymin * 1E13, (y1 - y0) * .1);
double y = y0 + bump;
if (!Double.isFinite(y1)) {
return 0;
}
while (y <= y1) {
if (fairlyClose(this.XforY(y), that.XforY(y))) {
if ((bump *= 2) > maxbump) {
@ -1319,7 +1322,7 @@ public abstract class Curve {
public boolean fairlyClose(double v1, double v2) {
return (Math.abs(v1 - v2) <
Math.max(Math.abs(v1), Math.abs(v2)) * 1E-10);
Math.max(Math.abs(v1), Math.abs(v2)) * 1E-8);
}
public abstract int getSegment(double[] coords);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. 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
@ -273,7 +273,7 @@ public class SSLFlowDelegate {
final SequentialScheduler scheduler;
volatile ByteBuffer readBuf;
volatile boolean completing;
boolean completing;
final ReentrantLock readBufferLock = new ReentrantLock();
final Logger debugr = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
@ -301,6 +301,11 @@ public class SSLFlowDelegate {
return enterReadScheduling();
}
@Override
public boolean closing() {
return closeNotifyReceived();
}
public final String dbgString() {
return "SSL Reader(" + tubeName + ")";
}
@ -505,7 +510,7 @@ public class SSLFlowDelegate {
if (result.handshaking()) {
handshaking = true;
if (debugr.on()) debugr.log("handshaking");
if (doHandshake(result, READER)) continue; // need unwrap
if (doHandshake(result.handshakeStatus(), READER)) continue; // need unwrap
else break; // doHandshake will have triggered the write scheduler if necessary
} else {
if (trySetALPN()) {
@ -550,6 +555,7 @@ public class SSLFlowDelegate {
private volatile Status lastUnwrapStatus;
EngineResult unwrapBuffer(ByteBuffer src) throws IOException {
assert readBufferLock.isHeldByCurrentThread();
ByteBuffer dst = getAppBuffer();
int len = src.remaining();
while (true) {
@ -573,6 +579,8 @@ public class SSLFlowDelegate {
break;
case CLOSED:
assert dst.position() == 0;
src.position(src.limit());
completing = true;
return doClosure(new EngineResult(sslResult));
case BUFFER_UNDERFLOW:
// handled implicitly by compaction/reallocation of readBuf
@ -834,7 +842,7 @@ public class SSLFlowDelegate {
boolean handshaking = false;
if (result.handshaking()) {
if (debugw.on()) debugw.log("handshaking");
doHandshake(result, WRITER); // ok to ignore return
doHandshake(result.handshakeStatus(), WRITER); // ok to ignore return
handshaking = true;
} else {
if (trySetALPN()) {
@ -1090,14 +1098,14 @@ public class SSLFlowDelegate {
return (current & HANDSHAKING);
};
private boolean doHandshake(EngineResult r, int caller) {
private boolean doHandshake(HandshakeStatus handshakeStatus, int caller) {
// unconditionally sets the HANDSHAKING bit, while preserving task bits
handshakeState.getAndAccumulate(0, (current, unused) -> HANDSHAKING | (current & TASK_BITS));
if (stateList != null && debug.on()) {
stateList.add(r.handshakeStatus().toString());
stateList.add(handshakeStatus.toString());
stateList.add(Integer.toString(caller));
}
switch (r.handshakeStatus()) {
switch (handshakeStatus) {
case NEED_TASK:
int s = handshakeState.accumulateAndGet(0, REQUEST_OR_DO_TASKS);
if ((s & REQUESTING_TASKS) > 0) { // someone else is or will do tasks
@ -1125,7 +1133,7 @@ public class SSLFlowDelegate {
break;
default:
throw new InternalError("Unexpected handshake status:"
+ r.handshakeStatus());
+ handshakeStatus);
}
return true;
}
@ -1182,34 +1190,20 @@ public class SSLFlowDelegate {
return false;
}
// FIXME: acknowledge a received CLOSE request from peer
EngineResult doClosure(EngineResult r) throws IOException {
if (debug.on())
debug.log("doClosure(%s): %s [isOutboundDone: %s, isInboundDone: %s]",
r.result, engine.getHandshakeStatus(),
engine.isOutboundDone(), engine.isInboundDone());
if (debug.on()) debug.log("doClosure: close_notify received");
close_notify_received = true;
engine.closeOutbound();
if (engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) {
// we have received TLS close_notify and need to send
// an acknowledgement back. We're calling doHandshake
// to finish the close handshake.
if (engine.isInboundDone() && !engine.isOutboundDone()) {
if (debug.on()) debug.log("doClosure: close_notify received");
close_notify_received = true;
if (!writer.scheduler.isStopped()) {
doHandshake(r, READER);
} else {
// We have received closed notify, but we
// won't be able to send the acknowledgement.
// Nothing more will come from the socket either,
// so mark the reader as completed.
var readerLock = reader.readBufferLock;
readerLock.lock();
try {
reader.completing = true;
} finally {
readerLock.unlock();
}
}
if (!writer.scheduler.isStopped()) {
doHandshake(HandshakeStatus.NEED_WRAP, READER);
}
}
return r;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. 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
@ -459,7 +459,7 @@ public abstract class SubscriberWrapper
}
void checkCompletion() {
if (downstreamCompleted || !upstreamCompleted) {
if (downstreamCompleted || (!upstreamCompleted && !completionAcknowledged)) {
return;
}
if (!outputQ.isEmpty()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. 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
@ -118,14 +118,7 @@ public class AesDkCrypto extends DkCrypto {
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
throws GeneralSecurityException {
int iter_count = DEFAULT_ITERATION_COUNT;
if (params != null) {
if (params.length != 4) {
throw new RuntimeException("Invalid parameter to stringToKey");
}
iter_count = readBigEndian(params, 0, 4);
}
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
byte[] tmpKey = randomToKey(PBKDF2(secret, salt, iter_count,
getKeySeedLength()));
byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
@ -485,17 +478,4 @@ public class AesDkCrypto extends DkCrypto {
return result;
}
public static final int readBigEndian(byte[] data, int pos, int size) {
int retVal = 0;
int shifter = (size-1)*8;
while (size > 0) {
retVal += (data[pos] & 0xff) << shifter;
shifter -= 8;
pos++;
size--;
}
return retVal;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. 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
@ -122,14 +122,7 @@ public class AesSha2DkCrypto extends DkCrypto {
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
throws GeneralSecurityException {
int iter_count = DEFAULT_ITERATION_COUNT;
if (params != null) {
if (params.length != 4) {
throw new RuntimeException("Invalid parameter to stringToKey");
}
iter_count = readBigEndian(params, 0, 4);
}
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
byte[] saltp = new byte[26 + 1 + salt.length];
if (keyLength == 128) {
System.arraycopy(ETYPE_NAME_128, 0, saltp, 0, 26);
@ -525,17 +518,4 @@ public class AesSha2DkCrypto extends DkCrypto {
return result;
}
public static final int readBigEndian(byte[] data, int pos, int size) {
int retVal = 0;
int shifter = (size-1)*8;
while (size > 0) {
retVal += (data[pos] & 0xff) << shifter;
shifter -= 8;
pos++;
size--;
}
return retVal;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
@ -31,8 +31,8 @@
package sun.security.krb5.internal.crypto.dk;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.util.Arrays;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -692,4 +692,41 @@ public abstract class DkCrypto {
bb.get(answer, 0, len);
return answer;
}
static int iterationCount(byte[] params, int defaultValue)
throws InvalidAlgorithmParameterException {
if (params == null) {
return defaultValue;
}
if (params.length != 4) {
throw new InvalidAlgorithmParameterException("Invalid params");
}
if (params[0] != 0 || ((params[1] & 0xff) >= 80)) {
// IC should be less than 80 * 2^16. This is roughly
// the same as PKCS12KeyStore's 5_000_000 limit.
throw new InvalidAlgorithmParameterException(
"Incoming iteration count is too big");
}
int iter_count = readBigEndian(params, 0, 4);
if (!ALLOW_WEAK_PBKDF2_ITERATION_COUNT && iter_count < defaultValue) {
throw new InvalidAlgorithmParameterException(
"Incoming iteration count is too small");
}
return iter_count;
}
public static final int readBigEndian(byte[] data, int pos, int size) {
int retVal = 0;
int shifter = (size-1)*8;
while (size > 0) {
retVal += (data[pos] & 0xff) << shifter;
shifter -= 8;
pos++;
size--;
}
return retVal;
}
// Only used by test
public static boolean ALLOW_WEAK_PBKDF2_ITERATION_COUNT = false;
}

View File

@ -34,6 +34,8 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlConfig;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@ -41,7 +43,7 @@ import org.xml.sax.InputSource;
* The XPathExpression interface encapsulates a (compiled) XPath expression.
*
* @author Ramesh Mandava
* @LastModified: May 2025
* @LastModified: Nov 2025
*/
public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression {
@ -51,7 +53,9 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
* from the context.
*/
protected XPathExpressionImpl() {
this(null, null, null, null, false, JdkXmlConfig.getInstance(false).getXMLFeatures(true));
this(null, null, null, null, false, JdkXmlConfig.getInstance(false).getXMLFeatures(true),
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
};
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
@ -59,13 +63,16 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
XPathFunctionResolver functionResolver,
XPathVariableResolver variableResolver) {
this(xpath, prefixResolver, functionResolver, variableResolver,
false, JdkXmlConfig.getInstance(false).getXMLFeatures(true));
false, JdkXmlConfig.getInstance(false).getXMLFeatures(true),
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
};
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver,
XPathVariableResolver variableResolver, boolean featureSecureProcessing,
JdkXmlFeatures featureManager) {
JdkXmlFeatures featureManager, XMLSecurityManager xmlSecMgr,
XMLSecurityPropertyManager xmlSecPropMgr) {
this.xpath = xpath;
this.prefixResolver = prefixResolver;
this.functionResolver = functionResolver;
@ -74,6 +81,8 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
this.overrideDefaultParser = featureManager.getFeature(
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
this.featureManager = featureManager;
this.xmlSecMgr = xmlSecMgr;
this.xmlSecPropMgr = xmlSecPropMgr;
};
public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath) {

View File

@ -51,7 +51,7 @@ import org.xml.sax.InputSource;
* New methods: evaluateExpression
* Refactored to share code with XPathExpressionImpl.
*
* @LastModified: June 2025
* @LastModified: Nov 2025
*/
public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
@ -175,7 +175,8 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
prefixResolver, functionResolver, variableResolver,
featureSecureProcessing, featureManager);
featureSecureProcessing, featureManager,
xmlSecMgr, xmlSecPropMgr);
return ximpl;
} catch (TransformerException te) {
throw new XPathExpressionException (te) ;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2025, Oracle and/or its affiliates. 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
@ -52,6 +52,7 @@ public class RFC396xTest {
public static void main(String[] args) throws Exception {
System.setProperty("sun.security.krb5.msinterop.des.s2kcharset",
"utf-8");
DkCrypto.ALLOW_WEAK_PBKDF2_ITERATION_COUNT = true;
test();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. 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
@ -38,11 +38,11 @@ public class DiffSaltParams {
OneKDC kdc = new OneKDC(null).writeJAASConf();
kdc.addPrincipal("user1", "user1pass".toCharArray(),
"hello", new byte[]{0, 0, 1, 0});
"hello", new byte[]{0, 1, 0, 0});
kdc.addPrincipal("user2", "user2pass".toCharArray(),
"hello", null);
kdc.addPrincipal("user3", "user3pass".toCharArray(),
null, new byte[]{0, 0, 1, 0});
null, new byte[]{0, 1, 0, 0});
kdc.addPrincipal("user4", "user4pass".toCharArray());
Context.fromUserPass("user1", "user1pass".toCharArray(), true);

View File

@ -366,11 +366,12 @@ public class KDC {
name.indexOf('/') < 0 ?
PrincipalName.KRB_NT_UNKNOWN :
PrincipalName.KRB_NT_SRV_HST);
ktab.addEntry(pn,
getSalt(pn),
pass,
kvno,
true);
int[] etypes = EType.getDefaults("default_tkt_enctypes");
EncryptionKey[] keys = new EncryptionKey[etypes.length];
for (int i = 0; i < etypes.length; i++) {
keys[i] = keyForUser(pn, etypes[i], false);
}
ktab.addEntry(pn, keys, kvno, true);
} else {
nativeKdc.ktadd(name, tab);
}
@ -671,10 +672,7 @@ public class KDC {
*/
private char[] getPassword(PrincipalName p, boolean server)
throws KrbException {
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
}
String pn = nameOf(p);
char[] pass = passwords.get(pn);
if (pass == null) {
throw new KrbException(server?
@ -690,10 +688,7 @@ public class KDC {
* @return the salt
*/
protected String getSalt(PrincipalName p) {
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
}
String pn = nameOf(p);
if (salts.containsKey(pn)) {
return salts.get(pn);
}
@ -725,10 +720,7 @@ public class KDC {
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
}
String pn = nameOf(p);
if (s2kparamses.containsKey(pn)) {
return s2kparamses.get(pn);
}
@ -742,6 +734,23 @@ public class KDC {
}
}
/**
* Returns the name of a PrincipalName inside KDC dbs.
* @param p the principal name
* @return the name
*/
private String nameOf(PrincipalName p) {
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
}
if (pn.startsWith("krbtgt/")) {
// We always register krbtgt using REALM
pn = "krbtgt/" + pn.substring(7).toUpperCase(Locale.ROOT);
}
return pn;
}
/**
* Returns the key for a given principal of the given encryption type
* @param p the principal

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8370615
* @summary Improve Kerberos credentialing
* @library /test/lib
* @compile -XDignore.symbol.file UserIterCount.java
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
* @run main/othervm -Djdk.net.hosts.file=TestHosts UserIterCount
*/
import java.util.HashMap;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.KrbException;
import sun.security.krb5.PrincipalName;
public class UserIterCount {
static class MyKDC extends OneKDC {
static final HashMap<String, EncryptionKey> CACHE
= new HashMap<>();
public MyKDC() throws Exception {
super(null);
}
@Override
protected byte[] getParams(PrincipalName p, int etype) {
if (etype == 18) {
if (p.toString().startsWith(OneKDC.USER)) {
return new byte[]{0, 0, 16, 01};
} else {
return new byte[]{0, 79, (byte)255, (byte)255};
}
} else {
return super.getParams(p, etype);
}
}
@Override
EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
throws KrbException {
var key = p.toString() + etype + server;
var v = CACHE.get(key);
if (v == null) {
v = super.keyForUser(p, etype, server);
CACHE.put(key, v);
}
return v;
}
}
public static void main(String[] args) throws Exception {
new MyKDC().writeJAASConf();
Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
Context.fromUserPass(OneKDC.USER2, OneKDC.PASS2, false);
}
}