mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8277489: Rewrite JAAS UnixLoginModule with FFM
Co-authored-by: Martin Doerr <mdoerr@openjdk.org> Reviewed-by: mdoerr, ascarpino, erikj
This commit is contained in:
parent
0d1d4d07b9
commit
eda15aa19c
@ -31,13 +31,14 @@ include LibCommon.gmk
|
|||||||
## Build libjaas
|
## Build libjaas
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
$(eval $(call SetupJdkLibrary, BUILD_LIBJAAS, \
|
ifeq ($(call isTargetOs, windows), true)
|
||||||
NAME := jaas, \
|
$(eval $(call SetupJdkLibrary, BUILD_LIBJAAS, \
|
||||||
OPTIMIZATION := LOW, \
|
NAME := jaas, \
|
||||||
EXTRA_HEADER_DIRS := java.base:libjava, \
|
OPTIMIZATION := LOW, \
|
||||||
LIBS_windows := advapi32.lib mpr.lib netapi32.lib user32.lib, \
|
EXTRA_HEADER_DIRS := java.base:libjava, \
|
||||||
))
|
LIBS_windows := advapi32.lib mpr.lib netapi32.lib user32.lib, \
|
||||||
|
))
|
||||||
TARGETS += $(BUILD_LIBJAAS)
|
|
||||||
|
|
||||||
|
TARGETS += $(BUILD_LIBJAAS)
|
||||||
|
endif
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|||||||
@ -274,7 +274,8 @@ module java.base {
|
|||||||
jdk.httpserver,
|
jdk.httpserver,
|
||||||
jdk.jlink,
|
jdk.jlink,
|
||||||
jdk.jpackage,
|
jdk.jpackage,
|
||||||
jdk.net;
|
jdk.net,
|
||||||
|
jdk.security.auth;
|
||||||
exports sun.net to
|
exports sun.net to
|
||||||
java.net.http,
|
java.net.http,
|
||||||
jdk.naming.dns;
|
jdk.naming.dns;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. 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
|
||||||
@ -26,7 +26,6 @@
|
|||||||
package com.sun.security.auth.module;
|
package com.sun.security.auth.module;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.IOException;
|
|
||||||
import javax.security.auth.*;
|
import javax.security.auth.*;
|
||||||
import javax.security.auth.callback.*;
|
import javax.security.auth.callback.*;
|
||||||
import javax.security.auth.login.*;
|
import javax.security.auth.login.*;
|
||||||
@ -34,6 +33,7 @@ import javax.security.auth.spi.*;
|
|||||||
import com.sun.security.auth.UnixPrincipal;
|
import com.sun.security.auth.UnixPrincipal;
|
||||||
import com.sun.security.auth.UnixNumericUserPrincipal;
|
import com.sun.security.auth.UnixNumericUserPrincipal;
|
||||||
import com.sun.security.auth.UnixNumericGroupPrincipal;
|
import com.sun.security.auth.UnixNumericGroupPrincipal;
|
||||||
|
import jdk.internal.util.OperatingSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@code LoginModule} imports a user's Unix
|
* This {@code LoginModule} imports a user's Unix
|
||||||
@ -121,20 +121,34 @@ public class UnixLoginModule implements LoginModule {
|
|||||||
*/
|
*/
|
||||||
public boolean login() throws LoginException {
|
public boolean login() throws LoginException {
|
||||||
|
|
||||||
long[] unixGroups = null;
|
// Fail immediately on Windows to avoid cygwin-like functions
|
||||||
|
// being loaded, which are not supported.
|
||||||
|
if (OperatingSystem.isWindows()) {
|
||||||
|
throw new FailedLoginException
|
||||||
|
("Failed in attempt to import " +
|
||||||
|
"the underlying system identity information" +
|
||||||
|
" on " + System.getProperty("os.name"));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ss = new UnixSystem();
|
ss = new UnixSystem();
|
||||||
} catch (UnsatisfiedLinkError ule) {
|
} catch (ExceptionInInitializerError | UnsatisfiedLinkError ule) {
|
||||||
|
// Errors could happen in either static blocks or the constructor,
|
||||||
|
// both have a cause.
|
||||||
succeeded = false;
|
succeeded = false;
|
||||||
throw new FailedLoginException
|
var error = new FailedLoginException
|
||||||
("Failed in attempt to import " +
|
("Failed in attempt to import " +
|
||||||
"the underlying system identity information" +
|
"the underlying system identity information" +
|
||||||
" on " + System.getProperty("os.name"));
|
" on " + System.getProperty("os.name"));
|
||||||
|
if (ule.getCause() != null) {
|
||||||
|
error.initCause(ule.getCause());
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
userPrincipal = new UnixPrincipal(ss.getUsername());
|
userPrincipal = new UnixPrincipal(ss.getUsername());
|
||||||
UIDPrincipal = new UnixNumericUserPrincipal(ss.getUid());
|
UIDPrincipal = new UnixNumericUserPrincipal(ss.getUid());
|
||||||
GIDPrincipal = new UnixNumericGroupPrincipal(ss.getGid(), true);
|
GIDPrincipal = new UnixNumericGroupPrincipal(ss.getGid(), true);
|
||||||
|
long[] unixGroups = null;
|
||||||
if (ss.getGroups() != null && ss.getGroups().length > 0) {
|
if (ss.getGroups() != null && ss.getGroups().length > 0) {
|
||||||
unixGroups = ss.getGroups();
|
unixGroups = ss.getGroups();
|
||||||
for (int i = 0; i < unixGroups.length; i++) {
|
for (int i = 0; i < unixGroups.length; i++) {
|
||||||
@ -150,9 +164,11 @@ public class UnixLoginModule implements LoginModule {
|
|||||||
"succeeded importing info: ");
|
"succeeded importing info: ");
|
||||||
System.out.println("\t\t\tuid = " + ss.getUid());
|
System.out.println("\t\t\tuid = " + ss.getUid());
|
||||||
System.out.println("\t\t\tgid = " + ss.getGid());
|
System.out.println("\t\t\tgid = " + ss.getGid());
|
||||||
unixGroups = ss.getGroups();
|
System.out.println("\t\t\tusername = " + ss.getUsername());
|
||||||
for (int i = 0; i < unixGroups.length; i++) {
|
if (unixGroups != null) {
|
||||||
System.out.println("\t\t\tsupp gid = " + unixGroups[i]);
|
for (int i = 0; i < unixGroups.length; i++) {
|
||||||
|
System.out.println("\t\t\tsupp gid = " + unixGroups[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
succeeded = true;
|
succeeded = true;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. 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
|
||||||
@ -25,38 +25,194 @@
|
|||||||
|
|
||||||
package com.sun.security.auth.module;
|
package com.sun.security.auth.module;
|
||||||
|
|
||||||
|
import jdk.internal.util.Architecture;
|
||||||
|
import jdk.internal.util.OperatingSystem;
|
||||||
|
|
||||||
|
import java.lang.foreign.AddressLayout;
|
||||||
|
import java.lang.foreign.Arena;
|
||||||
|
import java.lang.foreign.FunctionDescriptor;
|
||||||
|
import java.lang.foreign.GroupLayout;
|
||||||
|
import java.lang.foreign.Linker;
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
|
import java.lang.foreign.MemorySegment;
|
||||||
|
import java.lang.foreign.StructLayout;
|
||||||
|
import java.lang.foreign.SymbolLookup;
|
||||||
|
import java.lang.foreign.ValueLayout;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
|
|
||||||
|
import static java.lang.foreign.MemoryLayout.PathElement.groupElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implementation retrieves and makes available Unix
|
* This class implementation retrieves and makes available Unix
|
||||||
* UID/GID/groups information for the current user.
|
* UID/GID/groups information for the current user.
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
public class UnixSystem {
|
public class UnixSystem {
|
||||||
|
|
||||||
private native void getUnixInfo();
|
/**
|
||||||
|
* The current username.
|
||||||
// Warning: the following 4 fields are used by Unix.c
|
*/
|
||||||
|
|
||||||
/** The current username. */
|
|
||||||
protected String username;
|
protected String username;
|
||||||
|
|
||||||
/** The current user ID. */
|
/**
|
||||||
|
* The current user ID.
|
||||||
|
*/
|
||||||
protected long uid;
|
protected long uid;
|
||||||
|
|
||||||
/** The current group ID. */
|
/**
|
||||||
|
* The current group ID.
|
||||||
|
*/
|
||||||
protected long gid;
|
protected long gid;
|
||||||
|
|
||||||
/** The current list of groups. */
|
/**
|
||||||
|
* The current list of groups.
|
||||||
|
*/
|
||||||
protected long[] groups;
|
protected long[] groups;
|
||||||
|
|
||||||
|
private static final Linker LINKER = Linker.nativeLinker();
|
||||||
|
private static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup()
|
||||||
|
.or(LINKER.defaultLookup());
|
||||||
|
|
||||||
|
private static final ValueLayout.OfByte C_CHAR
|
||||||
|
= (ValueLayout.OfByte) LINKER.canonicalLayouts().get("char");
|
||||||
|
private static final ValueLayout.OfInt C_INT
|
||||||
|
= (ValueLayout.OfInt) LINKER.canonicalLayouts().get("int");
|
||||||
|
private static final ValueLayout.OfLong C_LONG
|
||||||
|
= (ValueLayout.OfLong) LINKER.canonicalLayouts().get("long");
|
||||||
|
private static final AddressLayout C_POINTER
|
||||||
|
= ((AddressLayout) LINKER.canonicalLayouts().get("void*"))
|
||||||
|
.withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR));
|
||||||
|
private static final ValueLayout C_SIZE_T
|
||||||
|
= (ValueLayout) LINKER.canonicalLayouts().get("size_t");
|
||||||
|
|
||||||
|
private static final StructLayout CAPTURE_STATE_LAYOUT
|
||||||
|
= Linker.Option.captureStateLayout();
|
||||||
|
private static final VarHandle VH_errno = CAPTURE_STATE_LAYOUT.varHandle(
|
||||||
|
MemoryLayout.PathElement.groupElement("errno"));
|
||||||
|
|
||||||
|
private static final MethodHandle MH_strerror
|
||||||
|
= LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow("strerror"),
|
||||||
|
FunctionDescriptor.of(C_POINTER, C_INT));
|
||||||
|
|
||||||
|
private static final MethodHandle MH_getgroups
|
||||||
|
= LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow("getgroups"),
|
||||||
|
FunctionDescriptor.of(C_INT, C_INT, C_POINTER),
|
||||||
|
Linker.Option.captureCallState("errno"));
|
||||||
|
private static final MethodHandle MH_getuid
|
||||||
|
= LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow("getuid"),
|
||||||
|
FunctionDescriptor.of(C_INT));
|
||||||
|
|
||||||
|
// Some architectures require appropriate zero or sign extension to 64 bit.
|
||||||
|
// Use long directly before https://bugs.openjdk.org/browse/JDK-8336664 is resolved.
|
||||||
|
private static final boolean calling_convention_requires_int_as_long
|
||||||
|
= Architecture.isPPC64() || Architecture.isPPC64LE() || Architecture.isS390();
|
||||||
|
|
||||||
|
// getpwuid_r does not work on AIX, instead we use another similar function
|
||||||
|
// extern int _posix_getpwuid_r(uid_t, struct passwd *, char *, int, struct passwd **)
|
||||||
|
private static final MethodHandle MH_getpwuid_r
|
||||||
|
= LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow(
|
||||||
|
OperatingSystem.isAix() ? "_posix_getpwuid_r" : "getpwuid_r"),
|
||||||
|
FunctionDescriptor.of(C_INT,
|
||||||
|
calling_convention_requires_int_as_long ? C_LONG : C_INT,
|
||||||
|
C_POINTER, C_POINTER,
|
||||||
|
OperatingSystem.isAix() ? C_INT : C_SIZE_T,
|
||||||
|
C_POINTER));
|
||||||
|
|
||||||
|
private static final GroupLayout ML_passwd = MemoryLayout.structLayout(
|
||||||
|
C_POINTER.withName("pw_name"),
|
||||||
|
C_POINTER.withName("pw_passwd"),
|
||||||
|
C_INT.withName("pw_uid"),
|
||||||
|
C_INT.withName("pw_gid"),
|
||||||
|
// Different platforms have different fields in `struct passwd`.
|
||||||
|
// While we don't need those fields here, the struct needs to be
|
||||||
|
// big enough to avoid buffer overflow when `getpwuid_r` is called.
|
||||||
|
MemoryLayout.paddingLayout(100));
|
||||||
|
|
||||||
|
private static final VarHandle VH_pw_uid
|
||||||
|
= ML_passwd.varHandle(groupElement("pw_uid"));
|
||||||
|
private static final VarHandle VH_pw_gid
|
||||||
|
= ML_passwd.varHandle(groupElement("pw_gid"));
|
||||||
|
private static final VarHandle VH_pw_name
|
||||||
|
= ML_passwd.varHandle(groupElement("pw_name"));
|
||||||
|
|
||||||
|
// The buffer size for the getpwuid_r function:
|
||||||
|
// 1. sysconf(_SC_GETPW_R_SIZE_MAX) on macOS is 4096 and 1024 on Linux,
|
||||||
|
// so we choose a bigger one.
|
||||||
|
// 2. We do not call sysconf() here because even _SC_GETPW_R_SIZE_MAX
|
||||||
|
// could be different on different platforms.
|
||||||
|
// 3. We choose int instead of long because the buffer_size argument
|
||||||
|
// might be `int` or `long` and converting from `long` to `int`
|
||||||
|
// requires an explicit cast.
|
||||||
|
private static final int GETPW_R_SIZE_MAX = 4096;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a {@code UnixSystem} and load
|
* Instantiate a {@code UnixSystem} and load
|
||||||
* the native library to access the underlying system information.
|
* the native library to access the underlying system information.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("restricted")
|
|
||||||
public UnixSystem() {
|
public UnixSystem() {
|
||||||
System.loadLibrary("jaas");
|
// The FFM code has only been tested on multiple platforms
|
||||||
getUnixInfo();
|
// (including macOS, Linux, AIX, etc) and might fail on other
|
||||||
|
// *nix systems. Especially, the `passwd` struct could be defined
|
||||||
|
// differently. I've checked several and an extra 100 chars at the
|
||||||
|
// end seems enough.
|
||||||
|
try (Arena scope = Arena.ofConfined()) {
|
||||||
|
MemorySegment capturedState = scope.allocate(CAPTURE_STATE_LAYOUT);
|
||||||
|
int groupnum = (int) MH_getgroups.invokeExact(capturedState, 0, MemorySegment.NULL);
|
||||||
|
if (groupnum == -1) {
|
||||||
|
throw new RuntimeException("getgroups returns " + groupnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
var gs = scope.allocate(C_INT, groupnum);
|
||||||
|
groupnum = (int) MH_getgroups.invokeExact(capturedState, groupnum, gs);
|
||||||
|
if (groupnum == -1) {
|
||||||
|
var errno = (int) VH_errno.get(capturedState, 0L);
|
||||||
|
var errMsg = (MemorySegment) MH_strerror.invokeExact(errno);
|
||||||
|
throw new RuntimeException("getgroups returns " + groupnum
|
||||||
|
+ ". Reason: " + errMsg.reinterpret(Long.MAX_VALUE).getString(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
groups = new long[groupnum];
|
||||||
|
for (int i = 0; i < groupnum; i++) {
|
||||||
|
groups[i] = Integer.toUnsignedLong(gs.getAtIndex(C_INT, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
var pwd = scope.allocate(ML_passwd);
|
||||||
|
var result = scope.allocate(C_POINTER);
|
||||||
|
var buffer = scope.allocate(GETPW_R_SIZE_MAX);
|
||||||
|
|
||||||
|
long tmpUid = Integer.toUnsignedLong((int) MH_getuid.invokeExact());
|
||||||
|
|
||||||
|
// Do not call invokeExact because the type of buffer_size is not
|
||||||
|
// always long in the underlying system.
|
||||||
|
int out;
|
||||||
|
if (calling_convention_requires_int_as_long) {
|
||||||
|
out = (int) MH_getpwuid_r.invoke(
|
||||||
|
tmpUid, pwd, buffer, GETPW_R_SIZE_MAX, result);
|
||||||
|
} else {
|
||||||
|
out = (int) MH_getpwuid_r.invoke(
|
||||||
|
(int) tmpUid, pwd, buffer, GETPW_R_SIZE_MAX, result);
|
||||||
|
}
|
||||||
|
if (out != 0) {
|
||||||
|
// If ERANGE (Result too large) is detected in a new platform,
|
||||||
|
// consider adjusting GETPW_R_SIZE_MAX.
|
||||||
|
var err = (MemorySegment) MH_strerror.invokeExact(out);
|
||||||
|
throw new RuntimeException(err.reinterpret(Long.MAX_VALUE).getString(0));
|
||||||
|
} else if (result.get(ValueLayout.ADDRESS, 0).equals(MemorySegment.NULL)) {
|
||||||
|
throw new RuntimeException("the requested entry is not found");
|
||||||
|
} else {
|
||||||
|
// uid_t and gid_t were defined unsigned.
|
||||||
|
uid = Integer.toUnsignedLong((int) VH_pw_uid.get(pwd, 0L));
|
||||||
|
gid = Integer.toUnsignedLong((int) VH_pw_gid.get(pwd, 0L));
|
||||||
|
username = ((MemorySegment) VH_pw_name.get(pwd, 0L)).getString(0);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
var error = new UnsatisfiedLinkError("FFM calls failed");
|
||||||
|
error.initCause(t);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2000, 2021, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include "jni_util.h"
|
|
||||||
#include "com_sun_security_auth_module_UnixSystem.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Declare library specific JNI_Onload entry if static build
|
|
||||||
*/
|
|
||||||
DEF_STATIC_JNI_OnLoad
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
|
||||||
Java_com_sun_security_auth_module_UnixSystem_getUnixInfo
|
|
||||||
(JNIEnv *env, jobject obj) {
|
|
||||||
|
|
||||||
int i;
|
|
||||||
char pwd_buf[1024];
|
|
||||||
struct passwd *pwd = NULL;
|
|
||||||
struct passwd resbuf;
|
|
||||||
jfieldID userNameID;
|
|
||||||
jfieldID userID;
|
|
||||||
jfieldID groupID;
|
|
||||||
jfieldID supplementaryGroupID;
|
|
||||||
|
|
||||||
jstring jstr;
|
|
||||||
jlongArray jgroups;
|
|
||||||
jlong *jgroupsAsArray;
|
|
||||||
jsize numSuppGroups;
|
|
||||||
gid_t *groups;
|
|
||||||
jclass cls;
|
|
||||||
|
|
||||||
numSuppGroups = getgroups(0, NULL);
|
|
||||||
if (numSuppGroups == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
|
|
||||||
if (groups == NULL) {
|
|
||||||
jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
|
|
||||||
if (cls != NULL) {
|
|
||||||
(*env)->ThrowNew(env, cls, NULL);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cls = (*env)->GetObjectClass(env, obj);
|
|
||||||
|
|
||||||
supplementaryGroupID = (*env)->GetFieldID(env, cls, "groups", "[J");
|
|
||||||
if (supplementaryGroupID == 0) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getgroups(numSuppGroups, groups) != -1) {
|
|
||||||
jgroups = (*env)->NewLongArray(env, numSuppGroups);
|
|
||||||
if (jgroups == NULL) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
|
|
||||||
if (jgroupsAsArray == NULL) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
for (i = 0; i < numSuppGroups; i++) {
|
|
||||||
jgroupsAsArray[i] = groups[i];
|
|
||||||
}
|
|
||||||
(*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
|
|
||||||
(*env)->SetObjectField(env, obj, supplementaryGroupID, jgroups);
|
|
||||||
}
|
|
||||||
|
|
||||||
userNameID = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
|
|
||||||
if (userNameID == 0) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
userID = (*env)->GetFieldID(env, cls, "uid", "J");
|
|
||||||
if (userID == 0) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
groupID = (*env)->GetFieldID(env, cls, "gid", "J");
|
|
||||||
if (groupID == 0) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(pwd_buf, 0, sizeof(pwd_buf));
|
|
||||||
if (getpwuid_r(getuid(), &resbuf, pwd_buf, sizeof(pwd_buf), &pwd) == 0 &&
|
|
||||||
pwd != NULL) {
|
|
||||||
(*env)->SetLongField(env, obj, userID, pwd->pw_uid);
|
|
||||||
(*env)->SetLongField(env, obj, groupID, pwd->pw_gid);
|
|
||||||
jstr = (*env)->NewStringUTF(env, pwd->pw_name);
|
|
||||||
if (jstr == NULL) {
|
|
||||||
goto cleanUpAndReturn;
|
|
||||||
}
|
|
||||||
(*env)->SetObjectField(env, obj, userNameID, jstr);
|
|
||||||
} else {
|
|
||||||
(*env)->SetLongField(env, obj, userID, getuid());
|
|
||||||
(*env)->SetLongField(env, obj, groupID, getgid());
|
|
||||||
}
|
|
||||||
cleanUpAndReturn:
|
|
||||||
free(groups);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. 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
|
||||||
@ -25,8 +25,11 @@
|
|||||||
* @test
|
* @test
|
||||||
* @bug 8039951
|
* @bug 8039951
|
||||||
* @summary com.sun.security.auth.module missing classes on some platforms
|
* @summary com.sun.security.auth.module missing classes on some platforms
|
||||||
|
* @modules java.base/jdk.internal.util
|
||||||
* @run main/othervm AllPlatforms
|
* @run main/othervm AllPlatforms
|
||||||
*/
|
*/
|
||||||
|
import jdk.internal.util.OperatingSystem;
|
||||||
|
|
||||||
import javax.security.auth.login.Configuration;
|
import javax.security.auth.login.Configuration;
|
||||||
import javax.security.auth.login.LoginContext;
|
import javax.security.auth.login.LoginContext;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -39,14 +42,14 @@ public class AllPlatforms {
|
|||||||
private static final String NT_MODULE = "NTLoginModule";
|
private static final String NT_MODULE = "NTLoginModule";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
login("cross-platform",
|
login(true, "cross-platform",
|
||||||
UNIX_MODULE, "optional",
|
UNIX_MODULE, "optional",
|
||||||
NT_MODULE, "optional");
|
NT_MODULE, "optional");
|
||||||
login("windows", NT_MODULE, "required");
|
login(OperatingSystem.isWindows(), "windows", NT_MODULE, "required");
|
||||||
login("unix", UNIX_MODULE, "required");
|
login(!OperatingSystem.isWindows(), "unix", UNIX_MODULE, "required");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void login(String test, String... conf) throws Exception {
|
static void login(boolean shouldSucceed, String test, String... conf) throws Exception {
|
||||||
System.out.println("Testing " + test + "...");
|
System.out.println("Testing " + test + "...");
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@ -68,11 +71,19 @@ public class AllPlatforms {
|
|||||||
lc.login();
|
lc.login();
|
||||||
System.out.println(lc.getSubject());
|
System.out.println(lc.getSubject());
|
||||||
lc.logout();
|
lc.logout();
|
||||||
|
if (!shouldSucceed) {
|
||||||
|
throw new RuntimeException("Should not succeed");
|
||||||
|
}
|
||||||
} catch (FailedLoginException e) {
|
} catch (FailedLoginException e) {
|
||||||
|
if (shouldSucceed) {
|
||||||
|
throw new RuntimeException("Should succeed");
|
||||||
|
}
|
||||||
// This exception can occur in other platform module than the running one.
|
// This exception can occur in other platform module than the running one.
|
||||||
if(e.getMessage().startsWith("Failed in attempt to import")) {
|
if (e.getMessage().startsWith("Failed in attempt to import")) {
|
||||||
System.out.println("Expected Exception found.");
|
System.out.println("Expected Exception found.");
|
||||||
e.printStackTrace(System.out);
|
e.printStackTrace(System.out);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unexpected error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user