-
Notifications
You must be signed in to change notification settings - Fork 250
debug SecureRandom #999
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?
debug SecureRandom #999
Conversation
which I do not see locally. |
|
https://github.com/openjdk/jdk21u-dev/blob/bad21fbe258402e7697279fdbdf7d67e02d20c03/src/java.base/windows/native/libjava/WinCAPISeedGenerator.c#L49C13-L52 alas this code does not call Could be some missing libraries in the container, could be permissions could be something entirely different... |
|
Cc @dduportal / @lemeurherve otherwise I’ll check later on. |
|
I would guess it is either |
|
I don’t think it’s in a container but will check when back to my laptop |
And here is how it's provisioned: https://github.com/jenkins-infra/packer-images/blob/main/provisioning/windows-provision.ps1 |
Adding to that, the default ec2 AMIs: https://github.com/jenkins-infra/jenkins-infra/blob/f67283f8dc6dac49954ba5407796bce2e1562eb8/hieradata/common.yaml#L222-L228, provisioned from https://github.com/jenkins-infra/packer-images cf comment above |
|
I logged into a running windows VM and ran: pwsh
cd C:\tools\jdk-17\bin
$url = 'https://gist.githubusercontent.com/timja/18b75ae57ecc2d517a8fce0811c98bdd/raw/83c73c7a59a8a3ef3b094166cdb9b35bf51ce7cb/gistfile1.txt'
Invoke-WebRequest $url -Outfile Main.java
.\javac Main.java
.\java '-Djava.security.debug="provider"' MainI tried it on Java 25 as well with the same result. |
|
I think best to just write a little C program and run it on the VM. |
|
Going to try this: |
|
This code (from mslearn on how to use the API): #include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
int main() {
printf("Debug Secure Random 2\n");
//-------------------------------------------------------------------
// Declare and initialize variables.
HCRYPTPROV hCryptProv = NULL; // handle for a cryptographic
// provider context
LPCSTR UserName = "J2SETest"; // name of the key container
// to be used
//-------------------------------------------------------------------
// Attempt to acquire a context and a key
// container. The context will use the default CSP
// for the RSA_FULL provider type. DwFlags is set to zero
// to attempt to open an existing key container.
if (CryptAcquireContext(
&hCryptProv, // handle to the CSP
UserName, // container name
NULL, // use the default provider
PROV_RSA_FULL, // provider type
0)) // flag values
{
printf("A cryptographic context with the %s key container \n",
UserName);
printf("has been acquired.\n\n");
}
else
{
//-------------------------------------------------------------------
// An error occurred in acquiring the context. This could mean
// that the key container requested does not exist. In this case,
// the function can be called again to attempt to create a new key
// container. Error codes are defined in Winerror.h.
DWORD errCode = GetLastError();
char errMsg[512];
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errCode,
0,
errMsg,
sizeof(errMsg),
NULL);
if (errCode == NTE_BAD_KEYSET)
{
if (CryptAcquireContext(
&hCryptProv,
UserName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("A new key container has been created.\n");
}
else
{
DWORD createErrCode = GetLastError();
char createErrMsg[512];
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
createErrCode,
0,
createErrMsg,
sizeof(createErrMsg),
NULL);
printf("Could not create a new key container. Error %lu: %s\n", createErrCode, createErrMsg);
fflush(stdout);
exit(1);
}
}
else
{
printf("A cryptographic service handle could not be acquired. Error %lu: %s\n", errCode, errMsg);
fflush(stdout);
exit(1);
}
} // End of else.
//-------------------------------------------------------------------
// A cryptographic context and a key container are available. Perform
// any functions that require a cryptographic provider handle.
//-------------------------------------------------------------------
// When the handle is no longer needed, it must be released.
if (CryptReleaseContext(hCryptProv, 0))
{
printf("The handle has been released.\n");
}
else
{
printf("The handle could not be released.\n");
}
}Works on my windows machine and fails on the VM with: |
|
Another iteration: |
|
The error handling there is questionable (no better then the JDK!l |
|
I've copiloted this: DWORD errCode = GetLastError();
char errMsg[512];
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errCode,
0,
errMsg,
sizeof(errMsg),
NULL);
printf("Could not create a new key container. Error %lu: %s\n", errCode, errMsg);
exit(1);trying now |
|
|
The user is running as an admin: PS Z:\jenkins\debug> $user = [Security.Principal.WindowsIdentity]::GetCurrent();
PS Z:\jenkins\debug> (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
True |
PS Z:\jenkins\debug> icacls "$env:APPDATA\Microsoft\Crypto\RSA"
Z:\jenkins\AppData\Roaming\Microsoft\Crypto\RSA NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
EC2AMAZ-44RG0FU\jenkins:(I)(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files |
|
With a different key container name: |
|
With more error handling: |
|
Hmm weird I thought I'd try on windows-2022 but my exe doesn't even run there =/ no error message or anything but nothing is outputted |
|
Here's the output running on windows 2022 anyway: https://ci.jenkins.io/job/Plugins/job/credentials-plugin/job/PR-999/8/pipeline-overview/log?nodeId=6 |
missing the specific vc runtime? |
|
Are you logged in via RDP to the console (for servers historically you needed to use the |
I'm logged in over SSH (which is the same as Jenkins is doing)
Probably |
|
New version should be statically linked: |
So you did not use the EC2 plugin to spin up your machine, is that correct? |
On AWS I used the EC2 plugin. On Azure I used the portal |
Sorry it was aimed at Jame, my bad |
|
After a pairing session with James:
Other considerations:
Code we used: |
|
asking about this on openssh windows port PowerShell/Win32-OpenSSH#2420 |
Could you clarify this? If you login with RDP then it is possible to use crypto from key based auth on an admin account.
Um I'm not sure, I feel at some point someone in one of the docker plugins was trying to get windows containers working I'm not sure if any plugins actually rely on it though. |
tested this locally and verified it works (server 2022)
my |
(you will possibly need to give the user the ability to create symlinks for |
Good point, I've updated the comment and I'm trying to verify the following scenario: a user (edit) Thanks for the external view. I confirm that the user can be in the Administrator group without any issue. It's only the SSH authentication technique which makes the crypto fail or not. |
I was doing all my testing on a pure EC2 VM created via the AWS console with the init script in user data |
|
so it may be we are not specifying the user correctly. As the machine is a domain controller the accounts need to be fully qualified (otherwise some things may not work). |
Oh oh, interesting one, thanks! I'm trying manually once to verify if it works |
|
More info on PowerShell/Win32-OpenSSH#2420 @dduportal |
Yup, I was checking PowerShell/Win32-OpenSSH#1597 (comment) :) |
At first try, it did not work: As admin: Then retrieved the domain with
|
are you sure that gets the domain? the domain and the computername are distinct (a domain can have multiple controllers and having a domain be the same name as the compute may well break something - so it would surprise me if this was the case) |
Well, launched an EC2 instance and it is not a domain server of 1 but a workgroup so that would be right.. 🤷
|
|
The commands described in https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-addomain?view=windowsserver2025-ps#example-2-get-domain-information-of-the-current-local-computer-domain are failing alas: The command does not seem present OOB. |
I'm now playing around with using the VM hostname instead of its IPv4 |
Using the hostname does not work either: same behavior. I'm going back to the password init in noninteractive |
|
AH I might have found a technique with the |
|
YEEEPEEKAY https://ci.jenkins.io/job/Infra/job/acceptance-tests/job/infra-checks/736/console |
|
Nice! Is Posh-SSH needed? Isn't the fix to do an SSH to localhost when the user is created using password auth first and then key based auth? The server should have SSH pre-installed on it? I guess it makes it easier to e.g. work with a password and use powershell objects |
Could be. I focused on validating the "patch" (e.g. verifying that the CryptoAPI can be used in the pipeline by performing a first SSH login with password in non interactive) and I wanted to rule out the "how to pass password to ssh client".
Exactly, that's why I started with it.
Absolutely. But the sequence of task is important:
|
|
So I'm not clear if the fix is just "ssh with user:pass" or if it you need to "run something that sets up the crypt API that has a user/PW token" If it's the latter then start-process will probably work to just run out debug tool and not need poshssh |
I initially thought we ran this scenario (setup CryptoAPI with the |
|
you don't reallay need to. just check the manually with |
Actually I do: it does not seem to do anything at all. I'm not sure what i'm missing in the call. generates the log files but they are empty (both of them). I can't even get an exit code. What is wrong with my instruction? |


diagnosis for #995 (comment) / jenkins-infra/helpdesk#4939
Testing done
Submitter checklist