Skip to content

Commit

Permalink
Merge pull request saltstack#305 from saltstack/cve/3003.4-pam-auth-fix
Browse files Browse the repository at this point in the history
CVE-2022-22967/3003.5 pam auth fix
  • Loading branch information
garethgreenaway authored May 12, 2022
2 parents 084d997 + 08acb9b commit 3d53101
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 19 deletions.
1 change: 1 addition & 0 deletions changelog/cve-2022-22967.security
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed PAM auth to reject auth attempt if user account is locked.
20 changes: 6 additions & 14 deletions salt/auth/pam.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# The pam components have been modified to be salty and have been taken from
# the pam module under this licence:
# (c) 2007 Chris AtLee <[email protected]>
Expand Down Expand Up @@ -35,8 +34,6 @@
"""

# Import Python Libs
from __future__ import absolute_import, print_function, unicode_literals

import logging
from ctypes import (
Expand All @@ -55,13 +52,8 @@
)
from ctypes.util import find_library

# Import Salt libs
import salt.utils.user

# Import 3rd-party libs
from salt.ext import six
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin

log = logging.getLogger(__name__)

try:
Expand Down Expand Up @@ -110,7 +102,7 @@ class PamMessage(Structure):
]

def __repr__(self):
return "<PamMessage {0} '{1}'>".format(self.msg_style, self.msg)
return "<PamMessage {} '{}'>".format(self.msg_style, self.msg)


class PamResponse(Structure):
Expand All @@ -124,7 +116,7 @@ class PamResponse(Structure):
]

def __repr__(self):
return "<PamResponse {0} '{1}'>".format(self.resp_retcode, self.resp)
return "<PamResponse {} '{}'>".format(self.resp_retcode, self.resp)


CONV_FUNC = CFUNCTYPE(
Expand Down Expand Up @@ -182,11 +174,11 @@ def authenticate(username, password):
"""
service = __opts__.get("auth.pam.service", "login")

if isinstance(username, six.text_type):
if isinstance(username, str):
username = username.encode(__salt_system_encoding__)
if isinstance(password, six.text_type):
if isinstance(password, str):
password = password.encode(__salt_system_encoding__)
if isinstance(service, six.text_type):
if isinstance(service, str):
service = service.encode(__salt_system_encoding__)

@CONV_FUNC
Expand Down Expand Up @@ -217,7 +209,7 @@ def my_conv(n_messages, messages, p_response, app_data):

retval = PAM_AUTHENTICATE(handle, 0)
if retval == 0:
PAM_ACCT_MGMT(handle, 0)
retval = PAM_ACCT_MGMT(handle, 0)
PAM_END(handle, 0)
return retval == 0

Expand Down
8 changes: 3 additions & 5 deletions salt/renderers/genshi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@
Genshi Renderer for Salt
"""

# pylint: disable=import-error,no-name-in-module
try:
from genshi.template import MarkupTemplate
from genshi.template import NewTextTemplate
from genshi.template import OldTextTemplate
from genshi.template import MarkupTemplate # pylint: disable=no-name-in-module
from genshi.template import NewTextTemplate # pylint: disable=no-name-in-module
from genshi.template import OldTextTemplate # pylint: disable=no-name-in-module

HAS_LIBS = True
except ImportError:
HAS_LIBS = False
# pylint: enable=import-error,no-name-in-module


def render(genshi_data, saltenv="base", sls="", method="xml", **kws):
Expand Down
36 changes: 36 additions & 0 deletions tests/pytests/unit/auth/test_pam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest
import salt.auth.pam
from tests.support.mock import patch

pytestmark = [
pytest.mark.skip_on_windows,
]


@pytest.fixture
def configure_loader_modules():
return {salt.auth.pam: {}}


@pytest.fixture
def mock_pam():
with patch("salt.auth.pam.CALLOC", autospec=True), patch(
"salt.auth.pam.pointer", autospec=True,
), patch("salt.auth.pam.PamHandle", autospec=True), patch(
"salt.auth.pam.PAM_START", autospec=True, return_value=0
), patch(
"salt.auth.pam.PAM_AUTHENTICATE", autospec=True, return_value=0
), patch(
"salt.auth.pam.PAM_END", autospec=True
):
yield


def test_cve_if_pam_acct_mgmt_returns_nonzero_authenticate_should_be_false(mock_pam):
with patch("salt.auth.pam.PAM_ACCT_MGMT", autospec=True, return_value=42):
assert salt.auth.pam.authenticate(username="fnord", password="fnord") is False


def test_if_pam_acct_mgmt_returns_zero_authenticate_should_be_true(mock_pam):
with patch("salt.auth.pam.PAM_ACCT_MGMT", autospec=True, return_value=0):
assert salt.auth.pam.authenticate(username="fnord", password="fnord") is True

0 comments on commit 3d53101

Please sign in to comment.