Clean the key when it is read

This commit is contained in:
Shane Lee 2024-02-05 15:11:46 -07:00 committed by Pedro Algarvio
parent bcd236d48c
commit c06ae0a939
3 changed files with 19 additions and 23 deletions

View file

@ -52,10 +52,6 @@ class ReqServerChannel:
transport = salt.transport.request_server(opts, **kwargs)
return cls(opts, transport)
@staticmethod
def _clean_key(key):
return key.strip().replace("\r", "").replace("\n", "")
def __init__(self, opts, transport):
self.opts = opts
self.transport = transport
@ -375,7 +371,7 @@ class ReqServerChannel:
elif os.path.isfile(pubfn):
# The key has been accepted, check it
with salt.utils.files.fopen(pubfn, "r") as pubfn_handle:
if self._clean_key(pubfn_handle.read()) != self._clean_key(load["pub"]):
if salt.crypt.clean_key(pubfn_handle.read()) != load["pub"]:
log.error(
"Authentication attempt from %s failed, the public "
"keys did not match. This may be an attempt to compromise "
@ -484,9 +480,7 @@ class ReqServerChannel:
# case. Otherwise log the fact that the minion is still
# pending.
with salt.utils.files.fopen(pubfn_pend, "r") as pubfn_handle:
if self._clean_key(pubfn_handle.read()) != self._clean_key(
load["pub"]
):
if salt.crypt.clean_key(pubfn_handle.read()) != load["pub"]:
log.error(
"Authentication attempt from %s failed, the public "
"key in pending did not match. This may be an "
@ -542,9 +536,7 @@ class ReqServerChannel:
# so, pass on doing anything here, and let it get automatically
# accepted below.
with salt.utils.files.fopen(pubfn_pend, "r") as pubfn_handle:
if self._clean_key(pubfn_handle.read()) != self._clean_key(
load["pub"]
):
if salt.crypt.clean_key(pubfn_handle.read()) != load["pub"]:
log.error(
"Authentication attempt from %s failed, the public "
"keys in pending did not match. This may be an "

View file

@ -80,6 +80,14 @@ if not HAS_M2 and not HAS_CRYPTO:
log = logging.getLogger(__name__)
def clean_key(key):
"""
Clean the key so that it only has unix style line endings (\\n)
"""
key = key.strip().split()
return "\n".join(key)
def dropfile(cachedir, user=None):
"""
Set an AES dropfile to request the master update the publish session key
@ -377,7 +385,7 @@ class MasterKeys(dict):
)
if os.path.isfile(self.sig_path):
with salt.utils.files.fopen(self.sig_path) as fp_:
self.pub_signature = fp_.read()
self.pub_signature = clean_key(fp_.read())
log.info(
"Read %s's signature from %s",
os.path.basename(self.pub_path),
@ -462,7 +470,7 @@ class MasterKeys(dict):
with salt.utils.files.fopen(path, "wb+") as wfh:
wfh.write(key.publickey().exportKey("PEM"))
with salt.utils.files.fopen(path) as rfh:
return rfh.read()
return clean_key(rfh.read())
def get_mkey_paths(self):
return self.pub_path, self.rsa_path
@ -942,7 +950,7 @@ class AsyncAuth:
except Exception: # pylint: disable=broad-except
pass
with salt.utils.files.fopen(self.pub_path) as f:
payload["pub"] = f.read()
payload["pub"] = clean_key(f.read())
return payload
def decrypt_aes(self, payload, master_pub=True):
@ -1165,11 +1173,9 @@ class AsyncAuth:
m_pub_exists = os.path.isfile(m_pub_fn)
if m_pub_exists and master_pub and not self.opts["open_mode"]:
with salt.utils.files.fopen(m_pub_fn) as fp_:
local_master_pub = fp_.read()
local_master_pub = clean_key(fp_.read())
if payload["pub_key"].replace("\n", "").replace(
"\r", ""
) != local_master_pub.replace("\n", "").replace("\r", ""):
if payload["pub_key"] != local_master_pub:
if not self.check_auth_deps(payload):
return ""

View file

@ -1,6 +1,6 @@
import pytest
import salt.channel.server as server
import salt.crypt as crypt
@pytest.fixture
@ -22,8 +22,7 @@ def key_data():
def test__clean_key(key_data, linesep):
tst_key = linesep.join(key_data)
chk_key = "\n".join(key_data)
clean_func = server.ReqServerChannel._clean_key
assert clean_func(tst_key) == clean_func(chk_key)
assert crypt.clean_key(tst_key) == crypt.clean_key(chk_key)
@pytest.mark.parametrize("linesep", ["\r\n", "\r", "\n"])
@ -31,5 +30,4 @@ def test__clean_key_mismatch(key_data, linesep):
tst_key = linesep.join(key_data)
tst_key = tst_key.replace("5", "4")
chk_key = "\n".join(key_data)
clean_func = server.ReqServerChannel._clean_key
assert clean_func(tst_key) != clean_func(chk_key)
assert crypt.clean_key(tst_key) != crypt.clean_key(chk_key)