From 8b909b87d87fd0b079b60a0e6693b578a3384efa Mon Sep 17 00:00:00 2001 From: nmoray Date: Tue, 24 Oct 2023 23:07:36 -0700 Subject: [PATCH 01/17] TACACSPLUS_PASSKEY_ENCRYPTION support --- scripts/hostcfgd | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index c4239199..ee47b0c2 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -57,6 +57,7 @@ LIMITS_CONF = "/etc/security/limits.conf" TACPLUS_SERVER_PASSKEY_DEFAULT = "" TACPLUS_SERVER_TIMEOUT_DEFAULT = "5" TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap" +TACACS_SECRET_SALT = "2e6593364d369fba925092e0c1c51466c276faa127f20d18cc5ed8ae52bedbcd" # RADIUS RADIUS_SERVER_AUTH_PORT_DEFAULT = "1812" @@ -76,6 +77,43 @@ CFG_DB = "CONFIG_DB" STATE_DB = "STATE_DB" +def get_salt(): + file_path = "/etc/shadow" + target_username = "admin" + salt = None + + # Read the file and search for the "admin" username + try: + with open(file_path, 'r') as file: + for line in file: + if "admin:" in line: + # Format: username:$id$salt$hashed + parts = line.split('$') + if len(parts) == 4: + salt = parts[2] + break + + except FileNotFoundError: + click.echo('File not found: ' % file_path) + except Exception as e: + print(f"An error occurred: {str(e)}") + click.echo('An error occurred: ' % str(e)) + + if salt == None: + salt = TACACS_SECRET_SALT + + return salt + +def decrypt_passkey(secret): + salt = get_salt() + print("from hostcfgd ", salt) + cmd = "echo " + format(secret) + " | openssl enc -aes-128-cbc -a -d -salt -pbkdf2 -pass pass:" + salt + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + output, errs = proc.communicate() + + if not errs: + output = output.decode('utf-8') + def signal_handler(sig, frame): if sig == signal.SIGHUP: syslog.syslog(syslog.LOG_INFO, "HostCfgd: signal 'SIGHUP' is caught and ignoring..") @@ -500,6 +538,13 @@ class AaaCfg(object): server = tacplus_global.copy() server['ip'] = addr server.update(self.tacplus_servers[addr]) + config_db = ConfigDBConnector() + config_db.connect() + output, errs = decrypt_passkey(server['passkey']) + if not errs: + server['passkey'] = output + else: + syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) servers_conf.append(server) servers_conf = sorted(servers_conf, key=lambda t: int(t['priority']), reverse=True) From 48e7d1d925599dccfc92d6a81b35e1cc00e30bb0 Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 06:41:35 -0700 Subject: [PATCH 02/17] code cleanup --- scripts/hostcfgd | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index ee47b0c2..899f5a45 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -96,7 +96,6 @@ def get_salt(): except FileNotFoundError: click.echo('File not found: ' % file_path) except Exception as e: - print(f"An error occurred: {str(e)}") click.echo('An error occurred: ' % str(e)) if salt == None: From c877edb5e825281a28da3c24c80e35797a454fd5 Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 07:35:46 -0700 Subject: [PATCH 03/17] Added syslogs --- scripts/hostcfgd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 899f5a45..290c859c 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -94,9 +94,9 @@ def get_salt(): break except FileNotFoundError: - click.echo('File not found: ' % file_path) + syslog.syslog(syslog.LOG_ERR, "File not found: {}".format(file_path)) except Exception as e: - click.echo('An error occurred: ' % str(e)) + syslog.syslog(syslog.LOG_ERR, "{}".format(str(e)) if salt == None: salt = TACACS_SECRET_SALT From b37ddcdc0b389ba63b74f1ebf6154a4ae2a25c3f Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 07:50:34 -0700 Subject: [PATCH 04/17] Removed debug prints --- scripts/hostcfgd | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 290c859c..d37ae1bf 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -105,7 +105,6 @@ def get_salt(): def decrypt_passkey(secret): salt = get_salt() - print("from hostcfgd ", salt) cmd = "echo " + format(secret) + " | openssl enc -aes-128-cbc -a -d -salt -pbkdf2 -pass pass:" + salt proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) output, errs = proc.communicate() From 945f4f20fb05f4d6d7d6391c82297778adb02edc Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 07:54:21 -0700 Subject: [PATCH 05/17] Fixed AUT issues --- scripts/hostcfgd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index d37ae1bf..52f9a47b 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -98,7 +98,7 @@ def get_salt(): except Exception as e: syslog.syslog(syslog.LOG_ERR, "{}".format(str(e)) - if salt == None: + if salt is None: salt = TACACS_SECRET_SALT return salt From 5b61c0c598ca2148b4205cdfb6679790fdf26ae9 Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 22:59:48 -0700 Subject: [PATCH 06/17] Fixed build issues --- scripts/hostcfgd | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 52f9a47b..93cb39cc 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -80,7 +80,7 @@ STATE_DB = "STATE_DB" def get_salt(): file_path = "/etc/shadow" target_username = "admin" - salt = None + salt = TACACS_SECRET_SALT # Read the file and search for the "admin" username try: @@ -98,9 +98,6 @@ def get_salt(): except Exception as e: syslog.syslog(syslog.LOG_ERR, "{}".format(str(e)) - if salt is None: - salt = TACACS_SECRET_SALT - return salt def decrypt_passkey(secret): From 7cb53e666f2c4cf2f1510b0727f078b0f98f1e3a Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 23:12:33 -0700 Subject: [PATCH 07/17] Fixed build issues --- scripts/hostcfgd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 93cb39cc..4f0e156e 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -96,8 +96,7 @@ def get_salt(): except FileNotFoundError: syslog.syslog(syslog.LOG_ERR, "File not found: {}".format(file_path)) except Exception as e: - syslog.syslog(syslog.LOG_ERR, "{}".format(str(e)) - + syslog.syslog(syslog.LOG_ERR, "output: {}".format(e.output)) return salt def decrypt_passkey(secret): From 43641de8dc70944a129b8fcd39aa89aa09d933e6 Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 25 Oct 2023 23:25:24 -0700 Subject: [PATCH 08/17] fixed build issues --- scripts/hostcfgd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 4f0e156e..49ec821e 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -96,7 +96,7 @@ def get_salt(): except FileNotFoundError: syslog.syslog(syslog.LOG_ERR, "File not found: {}".format(file_path)) except Exception as e: - syslog.syslog(syslog.LOG_ERR, "output: {}".format(e.output)) + syslog.syslog(syslog.LOG_ERR, "output: {}".format(str(e))) return salt def decrypt_passkey(secret): From 66b57b5848d86f82de5349ad00f26c3a3087ee19 Mon Sep 17 00:00:00 2001 From: nmoray Date: Thu, 26 Oct 2023 06:19:59 -0700 Subject: [PATCH 09/17] Added a check for passkey before appending into server configs --- scripts/hostcfgd | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 49ec821e..35a4c4d2 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -532,13 +532,14 @@ class AaaCfg(object): server = tacplus_global.copy() server['ip'] = addr server.update(self.tacplus_servers[addr]) - config_db = ConfigDBConnector() - config_db.connect() - output, errs = decrypt_passkey(server['passkey']) - if not errs: - server['passkey'] = output - else: - syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) + if server['passkey'] is not None: + config_db = ConfigDBConnector() + config_db.connect() + output, errs = decrypt_passkey(server['passkey']) + if not errs: + server['passkey'] = output + else: + syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) servers_conf.append(server) servers_conf = sorted(servers_conf, key=lambda t: int(t['priority']), reverse=True) From c6c8e0a1dd268ef71de7fb9316c41fe5c35375c1 Mon Sep 17 00:00:00 2001 From: nmoray Date: Thu, 26 Oct 2023 06:57:32 -0700 Subject: [PATCH 10/17] Fixed build issues --- scripts/hostcfgd | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 35a4c4d2..f4d28fa5 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -107,6 +107,7 @@ def decrypt_passkey(secret): if not errs: output = output.decode('utf-8') + return output, errs def signal_handler(sig, frame): if sig == signal.SIGHUP: From 977a268fd4ad4d45b885e4a767a4b831e93a1fd9 Mon Sep 17 00:00:00 2001 From: nmoray Date: Tue, 24 Oct 2023 23:07:36 -0700 Subject: [PATCH 11/17] TACACSPLUS_PASSKEY_ENCRYPTION support code cleanup Added syslogs Removed debug prints Fixed AUT issues Fixed build issues Fixed build issues fixed build issues Added a check for passkey before appending into server configs Fixed build issues --- scripts/hostcfgd | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index c4239199..f4d28fa5 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -57,6 +57,7 @@ LIMITS_CONF = "/etc/security/limits.conf" TACPLUS_SERVER_PASSKEY_DEFAULT = "" TACPLUS_SERVER_TIMEOUT_DEFAULT = "5" TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap" +TACACS_SECRET_SALT = "2e6593364d369fba925092e0c1c51466c276faa127f20d18cc5ed8ae52bedbcd" # RADIUS RADIUS_SERVER_AUTH_PORT_DEFAULT = "1812" @@ -76,6 +77,38 @@ CFG_DB = "CONFIG_DB" STATE_DB = "STATE_DB" +def get_salt(): + file_path = "/etc/shadow" + target_username = "admin" + salt = TACACS_SECRET_SALT + + # Read the file and search for the "admin" username + try: + with open(file_path, 'r') as file: + for line in file: + if "admin:" in line: + # Format: username:$id$salt$hashed + parts = line.split('$') + if len(parts) == 4: + salt = parts[2] + break + + except FileNotFoundError: + syslog.syslog(syslog.LOG_ERR, "File not found: {}".format(file_path)) + except Exception as e: + syslog.syslog(syslog.LOG_ERR, "output: {}".format(str(e))) + return salt + +def decrypt_passkey(secret): + salt = get_salt() + cmd = "echo " + format(secret) + " | openssl enc -aes-128-cbc -a -d -salt -pbkdf2 -pass pass:" + salt + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + output, errs = proc.communicate() + + if not errs: + output = output.decode('utf-8') + return output, errs + def signal_handler(sig, frame): if sig == signal.SIGHUP: syslog.syslog(syslog.LOG_INFO, "HostCfgd: signal 'SIGHUP' is caught and ignoring..") @@ -500,6 +533,14 @@ class AaaCfg(object): server = tacplus_global.copy() server['ip'] = addr server.update(self.tacplus_servers[addr]) + if server['passkey'] is not None: + config_db = ConfigDBConnector() + config_db.connect() + output, errs = decrypt_passkey(server['passkey']) + if not errs: + server['passkey'] = output + else: + syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) servers_conf.append(server) servers_conf = sorted(servers_conf, key=lambda t: int(t['priority']), reverse=True) From 0a1b098aab1955a4a52b6c0487728888c899e0fe Mon Sep 17 00:00:00 2001 From: nmoray Date: Thu, 26 Oct 2023 21:46:27 -0700 Subject: [PATCH 12/17] Fixed AUT issue --- .../sample_output/TACACS_config_db_local/tacplus_nss.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf b/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf index d24cab57..6c579ab8 100644 --- a/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf +++ b/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf @@ -29,8 +29,8 @@ local_authorization # server - set ip address, tcp port, secret string and timeout for TACACS+ servers # Default: None (no TACACS+ server) # server=1.1.1.1:49,secret=test,timeout=3 -server=192.168.1.1:50,secret=dellsonic,timeout=10,vrf=default -server=192.168.1.2:51,secret=dellsonic1,timeout=15,vrf=mgmt +server=192.168.1.1:50,secret=U2FsdGVkX19Ovnpox5mdiVHwoqkNeDobmnzQqubegqo=,timeout=10,vrf=default +server=192.168.1.2:51,secret=U2FsdGVkX18OobPGda1NvTYEHi9dk2zrrrDpBqiqHJ0=,timeout=15,vrf=mgmt # user_priv - set the map between TACACS+ user privilege and local user's passwd # Default: From 7b1478667427356050024d5eed44e3a9f109c31d Mon Sep 17 00:00:00 2001 From: nmoray Date: Thu, 26 Oct 2023 22:04:16 -0700 Subject: [PATCH 13/17] Fixed build issues --- .../TACACS_config_db_local/tacplus_nss.conf | 4 ++-- tests/hostcfgd/test_tacacs_vectors.py | 24 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf b/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf index 6c579ab8..d24cab57 100644 --- a/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf +++ b/tests/hostcfgd/sample_output/TACACS_config_db_local/tacplus_nss.conf @@ -29,8 +29,8 @@ local_authorization # server - set ip address, tcp port, secret string and timeout for TACACS+ servers # Default: None (no TACACS+ server) # server=1.1.1.1:49,secret=test,timeout=3 -server=192.168.1.1:50,secret=U2FsdGVkX19Ovnpox5mdiVHwoqkNeDobmnzQqubegqo=,timeout=10,vrf=default -server=192.168.1.2:51,secret=U2FsdGVkX18OobPGda1NvTYEHi9dk2zrrrDpBqiqHJ0=,timeout=15,vrf=mgmt +server=192.168.1.1:50,secret=dellsonic,timeout=10,vrf=default +server=192.168.1.2:51,secret=dellsonic1,timeout=15,vrf=mgmt # user_priv - set the map between TACACS+ user privilege and local user's passwd # Default: diff --git a/tests/hostcfgd/test_tacacs_vectors.py b/tests/hostcfgd/test_tacacs_vectors.py index b77fdeed..6350a949 100644 --- a/tests/hostcfgd/test_tacacs_vectors.py +++ b/tests/hostcfgd/test_tacacs_vectors.py @@ -46,7 +46,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "src_intf": "Ethernet0" } }, @@ -56,7 +56,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "vrf": "default" }, "192.168.1.2" : { @@ -64,7 +64,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "dellsonic1", + "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", "vrf": "mgmt" } }, @@ -108,7 +108,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "src_intf": "Ethernet0" } }, @@ -118,7 +118,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "vrf": "default" }, "192.168.1.2" : { @@ -126,7 +126,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "dellsonic1", + "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", "vrf": "mgmt" } }, @@ -170,7 +170,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "src_intf": "Ethernet0" } }, @@ -180,7 +180,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "vrf": "default" }, "192.168.1.2" : { @@ -188,7 +188,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "dellsonic1", + "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", "vrf": "mgmt" } }, @@ -232,7 +232,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "src_intf": "Ethernet0" } }, @@ -242,7 +242,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "dellsonic", + "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", "vrf": "default" }, "192.168.1.2" : { @@ -250,7 +250,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "dellsonic1", + "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", "vrf": "mgmt" } }, From 911e2c0b408422823c1b5d9f767539f43c0027e2 Mon Sep 17 00:00:00 2001 From: nmoray Date: Sun, 29 Oct 2023 22:04:34 -0700 Subject: [PATCH 14/17] Addressed comments --- scripts/hostcfgd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index f4d28fa5..db75371c 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -79,14 +79,14 @@ STATE_DB = "STATE_DB" def get_salt(): file_path = "/etc/shadow" - target_username = "admin" + target_username = "admin" + ":" salt = TACACS_SECRET_SALT # Read the file and search for the "admin" username try: with open(file_path, 'r') as file: for line in file: - if "admin:" in line: + if target_username in line: # Format: username:$id$salt$hashed parts = line.split('$') if len(parts) == 4: From bb5e5ee2fcee1948dd268fa6bbda13ea964e67ff Mon Sep 17 00:00:00 2001 From: nmoray Date: Thu, 23 Nov 2023 20:50:52 -0800 Subject: [PATCH 15/17] Incorporated security cipher class into the existing implemenatation --- scripts/hostcfgd | 44 +++------------------------ tests/hostcfgd/test_tacacs_vectors.py | 24 +++++++-------- 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index db75371c..31f53f55 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -17,6 +17,7 @@ from sonic_py_common.general import check_output_pipe from swsscommon.swsscommon import ConfigDBConnector, DBConnector, Table from swsscommon import swsscommon from sonic_installer import bootloader +from sonic_py_common.security_cipher import security_cipher # FILE PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic" @@ -57,7 +58,6 @@ LIMITS_CONF = "/etc/security/limits.conf" TACPLUS_SERVER_PASSKEY_DEFAULT = "" TACPLUS_SERVER_TIMEOUT_DEFAULT = "5" TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap" -TACACS_SECRET_SALT = "2e6593364d369fba925092e0c1c51466c276faa127f20d18cc5ed8ae52bedbcd" # RADIUS RADIUS_SERVER_AUTH_PORT_DEFAULT = "1812" @@ -76,39 +76,6 @@ DEFAULT_FIPS_RESTART_SERVICES = ['ssh', 'telemetry.service', 'restapi'] CFG_DB = "CONFIG_DB" STATE_DB = "STATE_DB" - -def get_salt(): - file_path = "/etc/shadow" - target_username = "admin" + ":" - salt = TACACS_SECRET_SALT - - # Read the file and search for the "admin" username - try: - with open(file_path, 'r') as file: - for line in file: - if target_username in line: - # Format: username:$id$salt$hashed - parts = line.split('$') - if len(parts) == 4: - salt = parts[2] - break - - except FileNotFoundError: - syslog.syslog(syslog.LOG_ERR, "File not found: {}".format(file_path)) - except Exception as e: - syslog.syslog(syslog.LOG_ERR, "output: {}".format(str(e))) - return salt - -def decrypt_passkey(secret): - salt = get_salt() - cmd = "echo " + format(secret) + " | openssl enc -aes-128-cbc -a -d -salt -pbkdf2 -pass pass:" + salt - proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) - output, errs = proc.communicate() - - if not errs: - output = output.decode('utf-8') - return output, errs - def signal_handler(sig, frame): if sig == signal.SIGHUP: syslog.syslog(syslog.LOG_INFO, "HostCfgd: signal 'SIGHUP' is caught and ignoring..") @@ -533,12 +500,11 @@ class AaaCfg(object): server = tacplus_global.copy() server['ip'] = addr server.update(self.tacplus_servers[addr]) - if server['passkey'] is not None: - config_db = ConfigDBConnector() - config_db.connect() - output, errs = decrypt_passkey(server['passkey']) + if ('key_encrypt' in server) and (server['key_encrypt']): + secure_cipher = security_cipher() + output, errs = secure_cipher.decrypt_passkey("TACPLUS", server['passkey']) if not errs: - server['passkey'] = output + server['passkey'] = output else: syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) servers_conf.append(server) diff --git a/tests/hostcfgd/test_tacacs_vectors.py b/tests/hostcfgd/test_tacacs_vectors.py index 6350a949..b77fdeed 100644 --- a/tests/hostcfgd/test_tacacs_vectors.py +++ b/tests/hostcfgd/test_tacacs_vectors.py @@ -46,7 +46,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "src_intf": "Ethernet0" } }, @@ -56,7 +56,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "vrf": "default" }, "192.168.1.2" : { @@ -64,7 +64,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", + "passkey": "dellsonic1", "vrf": "mgmt" } }, @@ -108,7 +108,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "src_intf": "Ethernet0" } }, @@ -118,7 +118,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "vrf": "default" }, "192.168.1.2" : { @@ -126,7 +126,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", + "passkey": "dellsonic1", "vrf": "mgmt" } }, @@ -170,7 +170,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "src_intf": "Ethernet0" } }, @@ -180,7 +180,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "vrf": "default" }, "192.168.1.2" : { @@ -188,7 +188,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", + "passkey": "dellsonic1", "vrf": "mgmt" } }, @@ -232,7 +232,7 @@ "global": { "auth_type": "chap", "timeout": 5, - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "src_intf": "Ethernet0" } }, @@ -242,7 +242,7 @@ "tcp_port": 50, "timeout": 10, "auth_type": "chap", - "passkey": "U2FsdGVkX1+hVtCDFDHckKVtuZsap88euNyLxGToWCw=", + "passkey": "dellsonic", "vrf": "default" }, "192.168.1.2" : { @@ -250,7 +250,7 @@ "tcp_port": 51, "timeout": 15, "auth_type": "pap", - "passkey": "U2FsdGVkX1/JWY/fktTzRyZbuUg79+BnvEn1jPupNCM=", + "passkey": "dellsonic1", "vrf": "mgmt" } }, From d7453645aabe54ac1a9c18edfe34f4c99bcabcf9 Mon Sep 17 00:00:00 2001 From: nmoray Date: Wed, 31 Jan 2024 21:56:55 -0800 Subject: [PATCH 16/17] Added a logic to remove the cipher pass file file encryption is disabled --- scripts/hostcfgd | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 31f53f55..0c8606ea 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -500,13 +500,17 @@ class AaaCfg(object): server = tacplus_global.copy() server['ip'] = addr server.update(self.tacplus_servers[addr]) - if ('key_encrypt' in server) and (server['key_encrypt']): + if 'key_encrypt' in server: secure_cipher = security_cipher() - output, errs = secure_cipher.decrypt_passkey("TACPLUS", server['passkey']) - if not errs: - server['passkey'] = output + if server['key_encrypt'] == 'True': + output, errs = secure_cipher.decrypt_passkey("TACPLUS", server['passkey']) + if not errs: + server['passkey'] = output + else: + syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) else: - syslog.syslog(syslog.LOG_ERR, "{}: decrypt_passkey failed.".format(addr)) + # Delete the cipher_pass file if exist + secure_cipher.del_cipher_pass() servers_conf.append(server) servers_conf = sorted(servers_conf, key=lambda t: int(t['priority']), reverse=True) From 1d85eb6dc3a191668a4d51871bb3d8bc32da6d4f Mon Sep 17 00:00:00 2001 From: nmoray Date: Fri, 12 Apr 2024 05:50:53 +0000 Subject: [PATCH 17/17] Updated class name --- scripts/hostcfgd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/hostcfgd b/scripts/hostcfgd index 0c8606ea..9646249f 100644 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -17,7 +17,7 @@ from sonic_py_common.general import check_output_pipe from swsscommon.swsscommon import ConfigDBConnector, DBConnector, Table from swsscommon import swsscommon from sonic_installer import bootloader -from sonic_py_common.security_cipher import security_cipher +from sonic_py_common.security_cipher import master_key_mgr # FILE PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic" @@ -501,7 +501,7 @@ class AaaCfg(object): server['ip'] = addr server.update(self.tacplus_servers[addr]) if 'key_encrypt' in server: - secure_cipher = security_cipher() + secure_cipher = master_key_mgr() if server['key_encrypt'] == 'True': output, errs = secure_cipher.decrypt_passkey("TACPLUS", server['passkey']) if not errs: