-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8349546: Linux support for Kerberos "nativeccache" functionality #28075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
8349546: Linux support for Kerberos "nativeccache" functionality #28075
Conversation
|
👋 Welcome back nrhall! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
Webrevs
|
|
Is there a particular reason for build.sh in the tests or are you just not familiar with how native test code gets automatically compiled by the makefiles based on file naming conventions? In short, any file |
Definitely the unfamiliar bit, although the build.sh was useful for doing some quick test runs. Is there an example you could point me at - I'd be happy to fix that. Edit: found some examples - fix incoming. |
|
@erikj79 I've had a go at the suggested changes - hope that's more what you were looking for? |
|
Thanks for all the help and pointers @erikj79 - I've pushed a commit to (hopefully) address all of your comments! |
erikj79
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a build point of view this is definitely starting to look better. I would like to get input from a reviewer in the component team at this point to comment on the validity of the change before I spend more time reviewing the build aspects.
|
Thanks for these @erikj79, no idea how I managed to miss at least one of those...! All addressed in latest commit. |
test/jdk/sun/security/krb5/native/libNativeCredentialCacheHelper.c
Outdated
Show resolved
Hide resolved
src/java.security.jgss/share/native/libkrb5shared/nativeccache.c
Outdated
Show resolved
Hide resolved
src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java
Outdated
Show resolved
Hide resolved
src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java
Outdated
Show resolved
Hide resolved
|
@smemery have pushed fixes for your comments. I've tested the changes on Linux, but don't have a Mac here today to test the build changes - so will attend to anything that fails in the CI. |
|
/reviewers 2 reviewer |
…ean-up of the test helper and the output it creates
|
Thanks for the work and maybe sorry for a dumb question but maybe it helps with documentation - if i get this right this only works for cases where the native client actually can extract the key credentials but not for things where a external component would be needed to apply them (like ssdp, tpm, sssd and the like, right?) |
Assuming I've understood your question:
Was that what you were getting at? |
|
I'm not sure if there's precedent for it in other That said, it's not clear that's needed for client applications that use the various security frameworks / principals in the JVM (where the stored keys in the principal are used), but could be useful for helper applications written in Java that do some kind of credential exchange to create a TGT, or perhaps things written partly in JNI. |
| public static native boolean setDefaultCache(String cacheName); | ||
| public static native boolean createInMemoryCacheFromFileCache(String inMemoryCacheName, String fileCacheName); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 newlines at the end. One is enough.
| * --add-exports java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED | ||
| * --add-exports java.security.jgss/sun.security.jgss.krb5=ALL-UNNAMED | ||
| * --add-exports java.base/sun.security.util=ALL-UNNAMED | ||
| * --add-exports java.base/jdk.internal.misc=ALL-UNNAMED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
@modules java.security.jgss/sun.security.krb5
java.security.jgss/sun.security.krb5.internal
...
It applies to both compile and run.
|
Hi @erikj79, I noticed that in our CI build the library is not built and the log shows How can we require them to be present? |
Is this intended to be a required dependency for OpenJDK or are you referring to how we would enable this feature and dependency for Oracle builds? If the latter, they would need to be part of the devkit that we use. So the first step would be to modify the devkit creation makefiles for Linux in You will also need to verify that libkrb5 is reasonably stable and compatible across versions, since we only build one JDK distribution per architecture for Linux. We use a sysroot from the oldest Linux distribution we support, so you would need to verify that linking against libkrb5 in that sysroot/devkit results in a JDK that is still runtime compatible with all the Linux versions we support. |
|
I am thinking this should be a required dependency. Otherwise, the JDK build will vary depending on the machine used. I don’t believe we’ve ever done this before (unless user explicitly specifies configure options), right? @nrhall, a related question: what if the library is available at build time but not at runtime? |
If libkrb5 available at build time, it will build the new JNI library/test etc as expected; if libkrb5 is then not available at runtime, the library will fail to load silently (once, and then will not be retried) - this was actually already part of the code, so I imagine this case has happened before somewhere already - see Credentials.java L446: I will say that libkrb5 is largely pretty stable (it's really old code with few features being added), though I'm not sure what range is required to be supported here in terms of operating system builds? Worst case though, any incompatibility will just result in this code not being used, although as it'd be a silent failure without debug flags, that's perhaps not ideal (but has always been the case, even before this change). |
|
@wangweij I've attended to your code review feedback above (and cleaned up a few other bits of the jtreg directives that weren't required). |
Two data points, but the JVM/krb5 library/jtreg test compiled on RHEL8 works on Ubuntu 24.04, and these two are reasonably far apart: Obviously the reverse doesn't work, but that's to be expected. |
|
|
Good point. I wonder what the intent of that exception handling code is, then. I assumed it was to silently fall back to using the pure Java code in the event a library was un-loadable / not present, etc. In this particular case, it's almost essential that this happens, because otherwise a JDK with this feature compiled in and distributed to a machine without libkrb5 installed would basically be unable to use anything that called the Looking at the code further: Of those, the libname is always a static string, so that just leaves the first two (or another |
|
For what it's worth, here's how this looks using KCM on a host... ...with libkrb5 installed: ...without libkrb5 installed: ...without libkrb5 installed, but with a small patch to also catch |
If we make I still think it should be a required dependency. |
|
There's prior art here for CUPS - this is a mandatory compile-time and run-time dependency. I guess the difference with CUPS is that Java can't print without it, whereas JAAS can auth using Kerberos without my code, it's just limited to a file ccache. It turns out that this limitation actually works to our advantage. The existing code will first try and use the pure Java code to acquire a file ccache using a series of hard-coded defaults: (I'm not sure of the provenance of 3 and 4, but 1 and 2 are reasonable) It then checks that the crypto is something it can handle. If the code successfully finds a supported ccache, it will succeed whether the new native lib is loadable or not. If it does not find a supported ccache this way, it will then try and load the native lib (and potentially fail with an (FWIW, I've tested this locally by temporarily making the system libkrb5 library inaccessible, then running a test with a regular FILE: ccache, and it worked as above.) Assuming we did build it in by default, I suspect most people using FILE: ccaches will not even get to the native library load - and anyone trying to use unsupported ccache types/crypto with an older Java version would have got an error anyway, it's just that now this might be an I imagine this code was written this way for similar reasons to the discussion we're having here, on whichever of Windows/MacOS this was first introduced. |
Purpose
This PR allows Linux based applications using JAAS to acquire Kerberos TGTs natively using the local system's Kerberos libraries/configuration, building on existing support on Windows/MacOSX.
Rationale
Currently the (pure java) JAAS codebase only supports file-based credential caches (ccaches). There are many other useful types of ccache accessible via the local system libraries; this change allows credentials to be acquired natively using those libraries, and thus adds support for all other ccache types supported by the local system (e.g. KCM, in-memory and kernel types), This support already exists on MacOSX and Windows.
The code change here largely uses the MacOSX code, edited for Linux with associated build system changes. It also adds an appropriate jtreg test which uses some native test helper code to manufacture an in-memory cache, and then uses the new code to acquire these credentials natively. This has been tested on Linux/Mac and the jtreg test passes on each (I couldn't see any existing tests on MacOSX for this feature).
Additionally this PR fixes a bug that's existed for a while (see L585-588 in
nativeccache.c) - without this code, this is a 100% reproducible segfault on Linux (it's unclear why this hasn't affected the Mac JVMs up to now, probably just no calling code that provides an empty list of addresses). It also fixes a (non problem) typo in the variable name in a function prototype.Implementation Detail
Note that there were multiple possible ways of doing this:
Duplicate the MacOSX
nativeccache.c, edit lightly for Linux and build a new library on Linux only (liblinuxkrb5), leaving MacOSX largely unchanged, but at the expense of this code duplication.Create a new shared library used on both platforms with conditional compilation to manage the differences. This necessitates a library name change on MacOSX and potentially knock-on packaging changes on that platform, which seemed a potentially expensive side-effect.
Create a shared
nativeccache.c(usingEXTRA_SRCin the build) and build separate MacOSX/Linux libraries. This allows the MacOSX library name to remain unchanged, and only adds a new library in Linux.I tried all three options; 3 seemed to be the best compromise all around, although is one of the options that effectively introduces a "no-op" change on MacOSX as a result. Hopefully the additional jtreg test is sufficient to compensate for this.
Interested to hear if anyone else has any suggestions for better ideas!
Notes
It wasn't clear to me what I should do with copyright headers/updating dates in headers. I've added similar boilerplate headers seen in other files to some of the new files, but please let me know what the usual form is here.
Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28075/head:pull/28075$ git checkout pull/28075Update a local copy of the PR:
$ git checkout pull/28075$ git pull https://git.openjdk.org/jdk.git pull/28075/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 28075View PR using the GUI difftool:
$ git pr show -t 28075Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28075.diff
Using Webrev
Link to Webrev Comment