Skip to content

Commit e253ea2

Browse files
committed
add kerberos retry with krb5config EBCDIC charset on z/os
1 parent ae763f2 commit e253ea2

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

dev/com.ibm.ws.security.spnego_fat/fat/src/com/ibm/ws/security/spnego/fat/ContainerKDCCommonTest.java

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 IBM Corporation and others.
2+
* Copyright (c) 2024, 2025 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License 2.0
55
* which accompanies this distribution, and is available at
@@ -17,6 +17,10 @@
1717

1818
import java.io.BufferedReader;
1919
import java.io.FileReader;
20+
import java.io.FileWriter;
21+
import java.io.IOException;
22+
import java.nio.charset.Charset;
23+
import java.nio.file.Files;
2024
import java.nio.file.Path;
2125
import java.nio.file.Paths;
2226
import java.text.DateFormat;
@@ -209,20 +213,34 @@ public static void createNewSpnegoToken(boolean setAsCommonSpnegoToken, boolean
209213
* @throws InterruptedException
210214
*/
211215
private static void createSpnegoToken(String thisMethod, String user, String password) throws Exception, InterruptedException {
216+
boolean retriedWithEbcdic = false;
212217
for (int i = 1; i <= 3; i++) {
213218
try {
214219
spnegoTokenForTestClass = createToken(user, password, TARGET_SERVER, null, null, configFile, krb5Helper, true, Krb5Helper.SPNEGO_MECH_OID, null);
215220
break;
216221
} catch (LoginException e) {
222+
Log.info(c, thisMethod, "Login still failed after " + i + " attempts");
217223
if (i == 3) {
218-
Log.info(c, thisMethod, "Login still failed after " + i + " attempts");
219224
String errorMsg = "Exception was caught while trying to create a SPNEGO token. Due to LoginException: " + e.getMessage();
220225
Log.error(c, thisMethod, e, errorMsg);
221226
e.printStackTrace();
222227
throw (new Exception(errorMsg, e));
223228
}
224229
Thread.sleep(2000);
225230
} catch (Exception e2) {
231+
// Check if this is a KrbException with status code 0 on z/OS
232+
if (!retriedWithEbcdic && isZOS() && isKrbExceptionWithStatusCode0(e2)) {
233+
Log.info(c, thisMethod, "Caught KrbException with status code 0 on z/OS. Attempting to convert krb5 config to EBCDIC and retry.");
234+
try {
235+
convertKrb5ConfigToEbcdic(configFile);
236+
retriedWithEbcdic = true;
237+
// Retry the token creation after conversion
238+
continue;
239+
} catch (IOException ioEx) {
240+
Log.error(c, thisMethod, ioEx, "Failed to convert krb5 config file to EBCDIC: " + ioEx.getMessage());
241+
// Fall through to throw the original exception
242+
}
243+
}
226244
String errorMsg = "Exception was caught while trying to create a SPNEGO token. Ensuing tests requiring use of this token might fail. " + e2.getMessage();
227245
Log.error(c, thisMethod, e2, errorMsg);
228246
e2.printStackTrace();
@@ -231,6 +249,53 @@ private static void createSpnegoToken(String thisMethod, String user, String pas
231249
}
232250
}
233251

252+
/**
253+
* Check if the current OS is z/OS
254+
*/
255+
private static boolean isZOS() {
256+
String osName = System.getProperty("os.name");
257+
return osName != null && osName.toLowerCase().contains("z/os");
258+
}
259+
260+
/**
261+
* Check if the exception is a com.ibm.security.krb5.KrbException with status code 0
262+
*/
263+
private static boolean isKrbExceptionWithStatusCode0(Exception e) {
264+
Throwable cause = e;
265+
while (cause != null) {
266+
String className = cause.getClass().getName();
267+
if ("com.ibm.security.krb5.KrbException".equals(className)) {
268+
String message = cause.getMessage();
269+
// Check if the message contains "status code: 0"
270+
if (message != null && message.contains("status code: 0")) {
271+
return true;
272+
}
273+
}
274+
cause = cause.getCause();
275+
}
276+
return false;
277+
}
278+
279+
/**
280+
* Convert the krb5 config file from ASCII to EBCDIC (IBM1047) charset
281+
*/
282+
private static void convertKrb5ConfigToEbcdic(String krb5ConfigPath) throws IOException {
283+
String method = "convertKrb5ConfigToEbcdic";
284+
Log.info(c, method, "Converting krb5 config file to EBCDIC: " + krb5ConfigPath);
285+
286+
Path configPath = Paths.get(krb5ConfigPath);
287+
288+
// Read the file content as ASCII
289+
String content = new String(Files.readAllBytes(configPath), Charset.forName("US-ASCII"));
290+
291+
// Write the content back using EBCDIC charset
292+
try (FileWriter writer = new FileWriter(configPath.toFile(), Charset.forName("IBM1047"))) {
293+
writer.write(content);
294+
}
295+
296+
Log.info(c, method, "Successfully converted krb5 config file to EBCDIC");
297+
}
298+
234299
public static String createToken(String username, String password, String targetServer, String realm, String kdcHostName, String krb5ConfPath,
235300
Krb5Helper krb5Helper, boolean includeClientGSSCredentialInSubject, Oid mechOid, String jaasLoginContextEntry) throws Exception {
236301
String method = "createToken";

0 commit comments

Comments
 (0)