*New 11.3 series Release:
2019-10-19: XigmaNAS 11.3.0.4.7014 - released

*New 12.0 series Release:
2019-10-05: XigmaNAS 12.0.0.4.6928 - released!

*New 11.2 series Release:
2019-09-23: XigmaNAS 11.2.0.4.6881 - released!

We really need "Your" help on XigmaNAS https://translations.launchpad.net/xigmanas translations. Please help today!

Producing and hosting XigmaNAS costs money. Please consider donating for our project so that we can continue to offer you the best.
We need your support! eg: PAYPAL

[SOLVED] How to read/write cert and key data from/to config file?

XigmaNAS Scripts and shell tips
Forum rules
Set-Up GuideFAQsForum Rules
Post Reply
User avatar
Snufkin
Advanced User
Advanced User
Posts: 289
Joined: 01 Jul 2012 11:27
Location: Etc/GMT-3 (BSD style)
Status: Offline

[SOLVED] How to read/write cert and key data from/to config file?

#1

Post by Snufkin » 24 Dec 2018 10:01

I'm testing PHP script to deploy cert/key pair for XigmaNAS web server.
Original script was presented by faust in [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI.

I've slightly modified it to enter cert/key pair not in system webui xml section

Code: Select all

$config['system']['webgui']['certificate'] = base64_encode($acme_cert);
$config['system']['webgui']['privatekey'] = base64_encode($acme_key);
but in web server xml section

Code: Select all

$config['websrv']['certificate'] = base64_encode($acme_cert);
$config['websrv']['privatekey'] = base64_encode($acme_key);
Modified PHP script runs twice a day using cron and works just fine.
It means script does nothing because cert file content is identical to the data from config.xml.

Code: Select all

$isnew_cert = (base64_encode($acme_cert) != $config['websrv']['certificate']);
Weird things happen when I push "Save and restart" button in Web server page.
Above comparison returns true and triggers cert/key to be written in config.

I've managed to output variable content to the screen and got strange results.
  1. Encoded data
    Cert file content, after base64_encode()

    Code: Select all

    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk...0tLS0K
    data drom config file

    Code: Select all

    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQ...RJRklDQVRFLS0tLS0NCg==
    Different length, looks different in console, PHP comparison "!=" returns "true".
    For no reason, command sequence behind "Save and restart" changed data in config.xml
  2. Decoded data
    Data from config file after base64_decode() and cert file content

    Code: Select all

    -----BEGIN CERTIFICATE-----
    MIIF3TCCBMWgAwIBAgISAw0reMh0AGpJjKoYcKgTCIGIMA0GCSqGSIb3DQEBCwUA
    ...
    eH/9iP8lSn4Ug/43glZ7oRE=
    -----END CERTIFICATE-----
    Equal length, looks identical in console, but PHP comparison "!=" returns "true".
    Although cert lines are the same visually, they are different, and this is NOT what I could understand.
Here I reached the limits of my knowledge and wanted to ask for help.
How to understand unexpected changes of the 1st point and "inequality of equals" of the 2nd point?
Last edited by Snufkin on 24 Dec 2018 20:55, edited 1 time in total.
XNAS 11.3.0.4 embedded, ASUS P5B-E, Intel DC E6600, 4 GB DDR2, 2 x HGST HDN726040ALE614, 2 x WDC WD5000AAKS, Ippon Back Power Pro 400

User avatar
ms49434
Developer
Developer
Posts: 718
Joined: 03 Sep 2015 18:49
Location: Neuenkirchen-Vörden, Germany - GMT+1
Contact:
Status: Offline

Re: [Q] How to read/write cert and key data from/to config file?

#2

Post by ms49434 » 24 Dec 2018 12:35

1. You are using loose comparison operator != which might return surprising results.
2. You are comparing encoded data but you really want to compare the original content.
3. You might want to use a function to compare strings.

If I were you I would user the following

Long version for better readability:

Code: Select all

$cert_last = trim(base64_decode($config['websrv']['certificate']));
$cert_next = trim($acme_cert);
if(0 === strcmp($cert_next,$cert_last)):
	$isnew_cert = false;
else:
	$isnew_cert = true;
endif;
Short version:

Code: Select all

$isnew_cert = (0 !== strcmp(trim($acme_cert),trim(base64_decode($config['websrv']['certificate']))));
1) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 22GB out of 32GB ECC RAM, LSI 9300-8i IT mode in passthrough mode. Pool 1: 2x HGST 10TB, mirrored, SLOG: Samsung 850 Pro, L2ARC: Samsung 850 Pro, Pool 2: 1x Samsung 860 EVO 1TB , services: Samba AD, CIFS/SMB, ftp, ctld, rsync, syncthing, zfs snapshots.
2) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 8GB out of 32GB ECC RAM, IBM M1215 crossflashed, IT mode, passthrough mode, 2x HGST 10TB , services: rsync.

User avatar
Snufkin
Advanced User
Advanced User
Posts: 289
Joined: 01 Jul 2012 11:27
Location: Etc/GMT-3 (BSD style)
Status: Offline

Re: [Q] How to read/write cert and key data from/to config file?

#3

Post by Snufkin » 24 Dec 2018 13:10

ms49434 wrote:
24 Dec 2018 12:35
1. You are using loose comparison operator != which might return surprising results.
2. You are comparing encoded data but you really want to compare the original content.
3. You might want to use a function to compare strings.

If I were you I would user the following

Long version for better readability:

Code: Select all

$cert_last = trim(base64_decode($config['websrv']['certificate']));
$cert_next = trim($acme_cert);
if(0 === strcmp($cert_next,$cert_last)):
	$isnew_cert = false;
else:
	$isnew_cert = true;
endif;
Short version:

Code: Select all

$isnew_cert = (0 !== strcmp(trim($acme_cert),trim(base64_decode($config['websrv']['certificate']))));
Thank you ms49434, your answer was just lightning fast.

Tested "long version" and got the same result.
I see both certs on screen the same, but strcmp() reports that they are different.

It seems Web server "Save and restart" adds/exchanges something among CR, LF, EOL or EOF unprintable symbols. And cert data from config file becomes different from cert file.
XNAS 11.3.0.4 embedded, ASUS P5B-E, Intel DC E6600, 4 GB DDR2, 2 x HGST HDN726040ALE614, 2 x WDC WD5000AAKS, Ippon Back Power Pro 400

User avatar
ms49434
Developer
Developer
Posts: 718
Joined: 03 Sep 2015 18:49
Location: Neuenkirchen-Vörden, Germany - GMT+1
Contact:
Status: Offline

Re: [Q] How to read/write cert and key data from/to config file?

#4

Post by ms49434 » 24 Dec 2018 17:42

Snufkin wrote:
24 Dec 2018 13:10
ms49434 wrote:
24 Dec 2018 12:35
1. You are using loose comparison operator != which might return surprising results.
2. You are comparing encoded data but you really want to compare the original content.
3. You might want to use a function to compare strings.

If I were you I would user the following

Long version for better readability:

Code: Select all

$cert_last = trim(base64_decode($config['websrv']['certificate']));
$cert_next = trim($acme_cert);
if(0 === strcmp($cert_next,$cert_last)):
	$isnew_cert = false;
else:
	$isnew_cert = true;
endif;
Short version:

Code: Select all

$isnew_cert = (0 !== strcmp(trim($acme_cert),trim(base64_decode($config['websrv']['certificate']))));
Thank you ms49434, your answer was just lightning fast.

Tested "long version" and got the same result.
I see both certs on screen the same, but strcmp() reports that they are different.

It seems Web server "Save and restart" adds/exchanges something among CR, LF, EOL or EOF unprintable symbols. And cert data from config file becomes different from cert file.
The WebGUI doesn't add or strip any information but I suspect that the browser itself modifies the data when submitting the form. To circumvent the issue with CRLF vs LF you can try a bigger gun:

Code: Select all

$cert_last = base64_decode($config['websrv']['certificate']);
$cert_next = $acme_cert;

$isnew_cert = false;
$cert_res_last = openssl_pkey_get_public($cert_last);
$cert_res_next = openssl_pkey_get_public($cert_next);
if(false !== $cert_res_next):
	if(false !== $cert_res_last):
		$cert_details_last = openssl_pkey_get_details($cert_res_last);
		$cert_details_next = openssl_pkey_get_details($cert_res_next);
		if(false !== $cert_details_next):
			if(false !== $cert_details_last):
				if(0 !== strcmp($cert_details_last['rsa']['n'],$cert_details_next['rsa']['n']) || 0 !== strcmp($cert_details_last['rsa']['e'],$cert_details_next['rsa']['e'])):
					$isnew_cert = true;
				endif;
			else:
				//	last certificate is not recognized, overwrite with next certificate
				$isnew_cert = true;
			endif;
/*
		else:
			//	new certificate is not recoginzed, do nothing
 */
		endif;
	else:
		//	last certificate is not recognized, overwrite with next certificate
		$isnew_cert = true;
	endif;
/*
else:
	//	new certificate is not recoginzed, do nothing
 */
endif;
1) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 22GB out of 32GB ECC RAM, LSI 9300-8i IT mode in passthrough mode. Pool 1: 2x HGST 10TB, mirrored, SLOG: Samsung 850 Pro, L2ARC: Samsung 850 Pro, Pool 2: 1x Samsung 860 EVO 1TB , services: Samba AD, CIFS/SMB, ftp, ctld, rsync, syncthing, zfs snapshots.
2) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 8GB out of 32GB ECC RAM, IBM M1215 crossflashed, IT mode, passthrough mode, 2x HGST 10TB , services: rsync.

User avatar
Snufkin
Advanced User
Advanced User
Posts: 289
Joined: 01 Jul 2012 11:27
Location: Etc/GMT-3 (BSD style)
Status: Offline

Re: [Q] How to read/write cert and key data from/to config file?

#5

Post by Snufkin » 24 Dec 2018 18:38

ms49434 wrote:
24 Dec 2018 17:42
To circumvent the issue with CRLF vs LF you can try a bigger gun
The power of this gun is overwhelming!
But it does its job, certs from one and the other sources are identified as the same.

Could this How to replace different newline styles in PHP be easier solution?

Edit
Tested Answer by Roey from above stackoverflow.com discussion.
Your first proposed "smaller gun" may look like this (to convert to LF only):

Code: Select all

$cert_last = str_replace("\r", '', trim(base64_decode($config['websrv']['certificate'])));
$cert_next = trim($acme_cert);
if(0 === strcmp($cert_next,$cert_last)):
	$isnew_cert = false;
else:
	$isnew_cert = true;
endif;
And it works.
Thus, with your help ms49434, I wrote my first line of PHP code. :o

Merry Xmas and happy New year!
XNAS 11.3.0.4 embedded, ASUS P5B-E, Intel DC E6600, 4 GB DDR2, 2 x HGST HDN726040ALE614, 2 x WDC WD5000AAKS, Ippon Back Power Pro 400

User avatar
ms49434
Developer
Developer
Posts: 718
Joined: 03 Sep 2015 18:49
Location: Neuenkirchen-Vörden, Germany - GMT+1
Contact:
Status: Offline

Re: [Q] How to read/write cert and key data from/to config file?

#6

Post by ms49434 » 24 Dec 2018 20:50

If the above code solves your case, go for it.

Merry Christmas!
1) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 22GB out of 32GB ECC RAM, LSI 9300-8i IT mode in passthrough mode. Pool 1: 2x HGST 10TB, mirrored, SLOG: Samsung 850 Pro, L2ARC: Samsung 850 Pro, Pool 2: 1x Samsung 860 EVO 1TB , services: Samba AD, CIFS/SMB, ftp, ctld, rsync, syncthing, zfs snapshots.
2) XigmaNAS 12.0.0.4 amd64-embedded on a Dell T20 running in a VM on ESXi 6.7U2, 8GB out of 32GB ECC RAM, IBM M1215 crossflashed, IT mode, passthrough mode, 2x HGST 10TB , services: rsync.

Post Reply

Return to “Scripts and shell tips”