glpi-project / glpi-agent

GLPI Agent
GNU General Public License v2.0
212 stars 51 forks source link

SSL error but CA is trusted in certstore windows #597

Closed wp-davga closed 4 months ago

wp-davga commented 4 months ago

Bug reporting acknowledgment

Yes, I read it

Professional support

I'm a GLPI partner

Describe the bug

Hello Everyone,

We are using a self-signed CA and a self-signed certificate to expose an HTTP proxy for GLPI. This is how I created the certificates:

#!/bin/bash

CANAME=GLPI-RootCA

mkdir $CANAME
cd $CANAME

openssl genrsa -aes256 -out $CANAME.key 4096

openssl req -x509 -new -nodes -key $CANAME.key -sha256 -days 1826 -out $CANAME.crt -subj '/CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye'

cp $CANAME.crt /etc/pki/ca-trust/source/anchors/$CANAME.crt
update-ca-trust

MYCERT=103956nesat03.wp.lan
openssl req -new -nodes -out $MYCERT.csr -newkey rsa:4096 -keyout $MYCERT.key -subj '/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye'

cat > $MYCERT.v3.ext << EOF
keyUsage                = critical,digitalSignature,keyEncipherment
basicConstraints        = CA:false
extendedKeyUsage        = serverAuth,clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always
subjectAltName = @alt_names

[alt_names]
DNS.1 = 103956nesat03.wp.lan
IP.1 = 10.62.8.21
EOF

openssl x509 -req -in $MYCERT.csr -extfile $MYCERT.v3.ext  -CA $CANAME.crt -CAkey $CANAME.key -CAcreateserial -out $MYCERT.crt.pem -days 730 -sha256

I have read the documentation, and I added our CA into the Windows 10 client certstore, but I still get an SSL error while trying to connect to GLPI. If I try to connect to the hostname the browser says that the certificate is valid.

This is how I install the GLPI-Agent msiexec /i GLPI-Agent-1.7.1-x86.msi /quiet SERVER=https://glpi_user:glpi_password@103956nesat03.wp.lan:443/glpi/front/inventory.php EXECMODE=1 DEBUG=2

This is how I test the connection glpi-agent --debug --debug --logger=stderr --tasks=collect --force

In the logs I can see that the certificate gets dumped into the GLPI-Agent keystore, but it still fails to validate the certificate.

[debug] [http client] Updating keystore known certificates
[debug2] Changing to 'C:/Program Files (x86)/GLPI-Agent/var/keystore-export-6YRPZb' temporary folder
[debug2] executing certutil -Silent -Split -Store CA
[debug2] executing certutil -Silent -Split -Store Root
[debug2] executing certutil -Silent -Split -Enterprise -Store CA
[debug2] executing certutil -Silent -Split -Enterprise -Store Root
[debug2] executing certutil -Silent -Split -GroupPolicy -Store CA
[debug2] executing certutil -Silent -Split -GroupPolicy -Store Root
[debug2] executing certutil -Silent -Split -User -Store CA
[debug2] executing certutil -Silent -Split -User -Store Root
[debug2] Changing back to 'C:/Program Files (x86)/GLPI-Agent' folder
DEBUG: .../IO/Socket/SSL.pm:3020: new ctx 82461248
DEBUG: .../IO/Socket/SSL.pm:705: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:707: socket connected
DEBUG: .../IO/Socket/SSL.pm:730: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:774: using SNI with hostname 103956nesat03.wp.lan
DEBUG: .../IO/Socket/SSL.pm:815: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:831: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (OUT), TLS handshake, Client hello (1)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:858: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:868: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:888: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (IN), TLS handshake, Server hello (2)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Certificate (11)
DEBUG: .../IO/Socket/SSL.pm:2864: ok=0 [0] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS alert, unknown CA (560)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:851: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:851: local error: SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:854: fatal SSL error: SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
DEBUG: .../lib/Net/HTTPS.pm:67: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed'
DEBUG: .../IO/Socket/SSL.pm:3069: free ctx 82461248 open=82461248
DEBUG: .../IO/Socket/SSL.pm:3073: free ctx 82461248 callback
DEBUG: .../IO/Socket/SSL.pm:3080: OK free ctx 82461248
[error] [http client] internal response: 500 Can't connect to 103956nesat03.wp.lan:443 (Bad file descriptor), SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
[error] No supported answer from server at https://glpi_user:glpi_password@103956nesat03.wp.lan:443/glpi/front/inventory.php`

I then tried to add both the Server Certificate and the CA in the certstore, still same error.

As a last option I modified the Mozilla::CA library to load my self-signed CA, and finally everything worked. I substitute the cacert.pem file and $host variable with '103956nesat03.wp.lan' instead of www.paypal.com

Here the log:

[debug] [http client] Updating keystore known certificates
[debug2] Changing to 'C:/Program Files (x86)/GLPI-Agent/var/keystore-export-LIL2Xl' temporary folder
[debug2] executing certutil -Silent -Split -Store CA
[debug2] executing certutil -Silent -Split -Store Root
[debug2] executing certutil -Silent -Split -Enterprise -Store CA
[debug2] executing certutil -Silent -Split -Enterprise -Store Root
[debug2] executing certutil -Silent -Split -GroupPolicy -Store CA
[debug2] executing certutil -Silent -Split -GroupPolicy -Store Root
[debug2] executing certutil -Silent -Split -User -Store CA
[debug2] executing certutil -Silent -Split -User -Store Root
[debug2] Changing back to 'C:/Program Files (x86)/GLPI-Agent' folder
DEBUG: .../IO/Socket/SSL.pm:3020: new ctx 62216296
DEBUG: .../IO/Socket/SSL.pm:705: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:707: socket connected
DEBUG: .../IO/Socket/SSL.pm:730: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:774: using SNI with hostname 103956nesat03.wp.lan
DEBUG: .../IO/Socket/SSL.pm:815: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:831: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (OUT), TLS handshake, Client hello (1)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:858: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:868: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:888: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (IN), TLS handshake, Server hello (2)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Certificate (11)
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [1] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [0] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:1840: scheme=www cert=72100664
DEBUG: .../IO/Socket/SSL.pm:1850: identity=103956nesat03.wp.lan cn=GLPI-Proxy alt=2 103956nesat03.wp.lan 7
§
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Server key exchange (12)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Server finished (14)
DEBUG: .../IO/Socket/SSL.pm:2911: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS handshake, Client key exchange (16)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS handshake, Finished (20)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:858: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:868: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:888: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Newsession Ticket (4)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Finished (20)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:903: ssl handshake done
[debug2] format: Zlib
[debug2] [http client] C7F7535C: received message:
{"message":"collect task not supported","disabled":["collect"],"expiration":"24","status":"ok"}
[debug] server message: collect task not supported
[debug2] [http client] Using Compress::Zlib for compression
DEBUG: .../IO/Socket/SSL.pm:3069: free ctx 62216296 open=62216296
DEBUG: .../IO/Socket/SSL.pm:3073: free ctx 62216296 callback
DEBUG: .../IO/Socket/SSL.pm:3080: OK free ctx 62216296
[info] sending prolog request to server0
[debug2] [http client] sending message:
<?xml version="1.0" encoding="UTF-8"?>
<REQUEST>
  <DEVICEID>DESKTOP-QG2A33O-2024-02-06-15-08-42</DEVICEID>
  <QUERY>PROLOG</QUERY>
  <TOKEN>12345678</TOKEN>
</REQUEST>
DEBUG: .../IO/Socket/SSL.pm:3020: new ctx 79563816
DEBUG: .../IO/Socket/SSL.pm:705: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:707: socket connected
DEBUG: .../IO/Socket/SSL.pm:730: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:774: using SNI with hostname 103956nesat03.wp.lan
DEBUG: .../IO/Socket/SSL.pm:815: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:831: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (OUT), TLS handshake, Client hello (1)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:858: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:868: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:888: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.3 (IN), TLS handshake, Server hello (2)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Certificate (11)
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [1] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [0] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:1840: scheme=www cert=72098504
DEBUG: .../IO/Socket/SSL.pm:1850: identity=103956nesat03.wp.lan cn=GLPI-Proxy alt=2 103956nesat03.wp.lan 7
§
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Server key exchange (12)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Server finished (14)
DEBUG: .../IO/Socket/SSL.pm:2911: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS handshake, Client key exchange (16)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (OUT), TLS handshake, Finished (20)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:858: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:868: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:888: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:845: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Newsession Ticket (4)
DEBUG: .../IO/Socket/SSL.pm:3700: * TLSv1.2 (IN), TLS handshake, Finished (20)
DEBUG: .../IO/Socket/SSL.pm:848: done Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:903: ssl handshake done
[debug2] format: Zlib
[debug2] [http client] receiving message:
<?xml version="1.0"?>
<REPLY><PROLOG_FREQ>24</PROLOG_FREQ><RESPONSE>SEND</RESPONSE></REPLY>
DEBUG: .../IO/Socket/SSL.pm:3069: free ctx 79563816 open=79563816
DEBUG: .../IO/Socket/SSL.pm:3073: free ctx 79563816 callback
DEBUG: .../IO/Socket/SSL.pm:3080: OK free ctx 79563816`

What I noticed is that before I tried my very nasty fix, the log says: DEBUG: .../IO/Socket/SSL.pm:2864: ok=0 [0] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye meanwhile after loading the CA as it was Mozilla's:

DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [1] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye
DEBUG: .../IO/Socket/SSL.pm:2864: ok=1 [0] /CN=GLPI Root CA/C=IT/ST=Bolzano/L=Bolzano/O=NetEye/CN=GLPI-Proxy/C=IT/ST=Bolzano/L=Bolzano/O=NetEye

I don't have enough Perl knowledge (I had none before this issue) to do further tests alone :)

Best Regards,

Davide

To reproduce

  1. Generate a CA and Certificate with the script provided
  2. Expose GLPI with the created certificate
  3. Add the CA into the Windows 10's certstore (in Trusted Root Certificate Authorities)
  4. Try to install and execute GLPI-Agent as described in the issue

Expected behavior

SSL errors in the log

Operating system

Windows

GLPI Agent version

1.7, Other (See additional context below)

GLPI version

10.0.10

GLPIInventory plugin or FusionInventory for GLPI plugin version

Not applicable

Additional context

I am using GLPI-Agent 1.7.1, but it is not available from the dropbox menu?

wp-davga commented 4 months ago

I also tried x64 1.7, same errors

g-bougard commented 4 months ago

Hi @wp-davga

when we see this:

[debug2] executing certutil -Silent -Split -Store CA
[debug2] executing certutil -Silent -Split -Store Root
[debug2] executing certutil -Silent -Split -Enterprise -Store CA
[debug2] executing certutil -Silent -Split -Enterprise -Store Root
[debug2] executing certutil -Silent -Split -GroupPolicy -Store CA
[debug2] executing certutil -Silent -Split -GroupPolicy -Store Root
[debug2] executing certutil -Silent -Split -User -Store CA
[debug2] executing certutil -Silent -Split -User -Store Root

This shows some store are exported but there's no line showing a certificate is found and imported.

So this means you installed your CA certificate is a keystore the agent is not exporting by default. Have you a keystore option to install your CA certificate ? Sorry I'm not an expert of certificate deployment.

Your test is clearly showing your certificate chain is valid and the problem is just the agent doesn't find the CA certificate it have to use.

If you can't install the CA certificate in one of the supported keystore, you still can use the ssl-fingerprint option or you'll have to deploy the CA certificate as a file and use ca-cert-file option to provide its path. But as I asked before, have you another choice for the keystore deployment ? You can also try to figure out which options are required for certutil to export your certificate, this may help to better understand if something is wrong in the deployment process or if we require to add its support in GLPI-Agent.

wp-davga commented 4 months ago

Hi @g-bougard

Thanks for the fast reply! I added a sleep function in Client.pm when the certificates gets dumped in C:/Program Files (x86)/GLPI-Agent/var/keystore-export-LIL2Xl. I confirm that in the temp folder my certificate is present. The certutil commands are working and they dump my CA certificate. For this reason, I still think there is a bug somewhere when the certificates get dumped in GLPI's keystore from the keystore-export temp folder.

I tried ca-cert-file and I confirm that by using that flag I have the same exact logs as when I modified the Mozilla::CA library. We would like to avoid using this route.

g-bougard commented 4 months ago

Hi @wp-davga

this is weird.

Actually, glpi-agent expects to find some *.crt files under the temporary folder and it has to convert any with certutil -encode "filename.crt" temp.cer. But as we don't see this kind of execution in your log, I can only assume the agent doesn't find the file.

So how is named the certificate you found ?

Another point can tell us which OS version you're using ?

Last point as I see you have agent installed under C:\Program Files (x86)\GLPI-Agent, can I assume you installed x86 version on a x64 computer ? So can you try with glpi-agent x64 version ? Just to be sure this is not related.

wp-davga commented 4 months ago

Hi @g-bougard

Now I understand what you mean. I used the x86 client as I could not use the 1.7.1 x64 due to a generic error. I retried again with the 1.7.1 x64 and I can see the file getting encoded. [debug2] executing certutil -encode xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.crt temp.cer

and the connection works. I don't know why the 1.7.1 x86 client was not encoding these certificates or why the 1.7 x64 client as well was not encoding. As I said I added a sleep function in perl/agent/GLPI/Agent/HTTP/Client.pm inside this foreach loop:

foreach my $certfile (File::Glob:bsd_glob)("$certdir/*")) {

and I could see my certificate in the temp folder, and each certificate disappearing from that folder in sequential order, but I had no logs as you noticed about the encoding.

I would close this issue as our case has been resolved, I don't know if you want to try to reproduce the problems for 1.7 x64 and 1.7.1 x86 client.

Thanks for your support!!

g-bougard commented 4 months ago

Okay, nice to see your problem is finally gone with x64 version. Actually, I can only assume bsd_glob() api is not doing its job under x86 or there's another issue somewhere around. But I won't investigate as you're the first to report this problem and next version won't include a x86 version. Thank you for your nice debugging efforts.