prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Backport] GHSA-mcg6-h362-cmq5
  ### Original feature issue
  
  - Advisory: https://github.com/advisories/GHSA-mcg6-h362-cmq5
  
  ### Target release
  
  - [ ] release33
  - [x] release32
  - [ ] release30
  
  ### Reason
  
  Stabilization of Cobbler 3.2.x in the Fedora Ecosystem
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `cobbler/modules/authentication/pam.py`
  Content:
  ```
  1 """
  2 Authentication module that uses /etc/cobbler/auth.conf
  3 Choice of authentication module is in /etc/cobbler/modules.conf
  4 
  5 Copyright 2007-2009, Red Hat, Inc and Others
  6 Michael DeHaan <michael.dehaan AT gmail>
  7 
  8 This program is free software; you can redistribute it and/or modify
  9 it under the terms of the GNU General Public License as published by
  10 the Free Software Foundation; either version 2 of the License, or
  11 (at your option) any later version.
  12 
  13 This program is distributed in the hope that it will be useful,
  14 but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 GNU General Public License for more details.
  17 
  18 You should have received a copy of the GNU General Public License
  19 along with this program; if not, write to the Free Software
  20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21 02110-1301  USA
  22 
  23 PAM python code based on the pam_python code created by Chris AtLee:
  24 http://atlee.ca/software/pam/
  25 
  26 #-----------------------------------------------
  27 pam_python (c) 2007 Chris AtLee <chris@atlee.ca>
  28 Licensed under the MIT license:
  29 http://www.opensource.org/licenses/mit-license.php
  30 
  31 PAM module for python
  32 
  33 Provides an authenticate function that will allow the caller to authenticate
  34 a user against the Pluggable Authentication Modules (PAM) on the system.
  35 
  36 Implemented using ctypes, so no compilation is necessary.
  37 """
  38 
  39 from ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, pointer, sizeof
  40 from ctypes import c_void_p, c_uint, c_char_p, c_char, c_int
  41 from ctypes.util import find_library
  42 
  43 LIBPAM = CDLL(find_library("pam"))
  44 LIBC = CDLL(find_library("c"))
  45 
  46 CALLOC = LIBC.calloc
  47 CALLOC.restype = c_void_p
  48 CALLOC.argtypes = [c_uint, c_uint]
  49 
  50 STRDUP = LIBC.strdup
  51 STRDUP.argstypes = [c_char_p]
  52 STRDUP.restype = POINTER(c_char)        # NOT c_char_p !!!!
  53 
  54 # Various constants
  55 PAM_PROMPT_ECHO_OFF = 1
  56 PAM_PROMPT_ECHO_ON = 2
  57 PAM_ERROR_MSG = 3
  58 PAM_TEXT_INFO = 4
  59 
  60 
  61 def register() -> str:
  62     """
  63     The mandatory Cobbler module registration hook.
  64     """
  65     return "authn"
  66 
  67 
  68 class PamHandle(Structure):
  69     """
  70     wrapper class for pam_handle_t
  71     """
  72     _fields_ = [("handle", c_void_p)]
  73 
  74     def __init__(self):
  75         Structure.__init__(self)
  76         self.handle = 0
  77 
  78 
  79 class PamMessage(Structure):
  80     """
  81     wrapper class for pam_message structure
  82     """
  83     _fields_ = [("msg_style", c_int), ("msg", c_char_p)]
  84 
  85     def __repr__(self):
  86         return "<PamMessage %i '%s'>" % (self.msg_style, self.msg)
  87 
  88 
  89 class PamResponse(Structure):
  90     """
  91     wrapper class for pam_response structure
  92     """
  93     _fields_ = [("resp", c_char_p), ("resp_retcode", c_int)]
  94 
  95     def __repr__(self):
  96         return "<PamResponse %i '%s'>" % (self.resp_retcode, self.resp)
  97 
  98 
  99 CONV_FUNC = CFUNCTYPE(c_int, c_int, POINTER(POINTER(PamMessage)), POINTER(POINTER(PamResponse)), c_void_p)
  100 
  101 
  102 class PamConv(Structure):
  103     """
  104     wrapper class for pam_conv structure
  105     """
  106     _fields_ = [("conv", CONV_FUNC), ("appdata_ptr", c_void_p)]
  107 
  108 
  109 PAM_START = LIBPAM.pam_start
  110 PAM_START.restype = c_int
  111 PAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)]
  112 
  113 PAM_AUTHENTICATE = LIBPAM.pam_authenticate
  114 PAM_AUTHENTICATE.restype = c_int
  115 PAM_AUTHENTICATE.argtypes = [PamHandle, c_int]
  116 
  117 
  118 def authenticate(api_handle, username: str, password: str) -> bool:
  119     """
  120     :param api_handle: Used for resolving the the pam service name and getting the Logger.
  121     :param username:The username to log in with.
  122     :param password: The password to log in with.
  123     :returns: True if the given username and password authenticate for the given service. Otherwise False
  124     """
  125 
  126     @CONV_FUNC
  127     def my_conv(n_messages, messages, p_response, app_data):
  128         """
  129         Simple conversation function that responds to any prompt where the echo is off with the supplied password
  130         """
  131         # Create an array of n_messages response objects
  132         addr = CALLOC(n_messages, sizeof(PamResponse))
  133         p_response[0] = cast(addr, POINTER(PamResponse))
  134         for i in range(n_messages):
  135             if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
  136                 pw_copy = STRDUP(password.encode())
  137                 p_response.contents[i].resp = cast(pw_copy, c_char_p)
  138                 p_response.contents[i].resp_retcode = 0
  139         return 0
  140 
  141     try:
  142         service = api_handle.settings().authn_pam_service
  143     except:
  144         service = 'login'
  145 
  146     api_handle.logger.debug("authn_pam: PAM service is %s" % service)
  147 
  148     handle = PamHandle()
  149     conv = PamConv(my_conv, 0)
  150     retval = PAM_START(service.encode(), username.encode(), pointer(conv), pointer(handle))
  151 
  152     if retval != 0:
  153         # TODO: This is not an authentication error, something has gone wrong starting up PAM
  154         api_handle.logger.error("authn_pam: error initializing PAM library")
  155         return False
  156 
  157     retval = PAM_AUTHENTICATE(handle, 0)
  158     return retval == 0
  159
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/cobbler/modules/authentication/pam.py b/cobbler/modules/authentication/pam.py
  --- a/cobbler/modules/authentication/pam.py
  +++ b/cobbler/modules/authentication/pam.py
  @@ -114,6 +114,10 @@
   PAM_AUTHENTICATE.restype = c_int
   PAM_AUTHENTICATE.argtypes = [PamHandle, c_int]
   
  +PAM_ACCT_MGMT = LIBPAM.pam_acct_mgmt
  +PAM_ACCT_MGMT.restype = c_int
  +PAM_ACCT_MGMT.argtypes = [PamHandle, c_int]
  +
   
   def authenticate(api_handle, username: str, password: str) -> bool:
       """
  @@ -155,4 +159,8 @@
           return False
   
       retval = PAM_AUTHENTICATE(handle, 0)
  +
  +    if retval == 0:
  +        retval = PAM_ACCT_MGMT(handle, 0)
  +
       return retval == 0
  
verification_info: {"golden_diff": "diff --git a/cobbler/modules/authentication/pam.py b/cobbler/modules/authentication/pam.py\n--- a/cobbler/modules/authentication/pam.py\n+++ b/cobbler/modules/authentication/pam.py\n@@ -114,6 +114,10 @@\n PAM_AUTHENTICATE.restype = c_int\n PAM_AUTHENTICATE.argtypes = [PamHandle, c_int]\n \n+PAM_ACCT_MGMT = LIBPAM.pam_acct_mgmt\n+PAM_ACCT_MGMT.restype = c_int\n+PAM_ACCT_MGMT.argtypes = [PamHandle, c_int]\n+\n \n def authenticate(api_handle, username: str, password: str) -> bool:\n     \"\"\"\n@@ -155,4 +159,8 @@\n         return False\n \n     retval = PAM_AUTHENTICATE(handle, 0)\n+\n+    if retval == 0:\n+        retval = PAM_ACCT_MGMT(handle, 0)\n+\n     return retval == 0\n", "issue": "[Backport] GHSA-mcg6-h362-cmq5\n### Original feature issue\r\n\r\n- Advisory: https://github.com/advisories/GHSA-mcg6-h362-cmq5\r\n\r\n### Target release\r\n\r\n- [ ] release33\r\n- [x] release32\r\n- [ ] release30\r\n\r\n### Reason\r\n\r\nStabilization of Cobbler 3.2.x in the Fedora Ecosystem\r\n\n", "before_files": [{"content": "\"\"\"\nAuthentication module that uses /etc/cobbler/auth.conf\nChoice of authentication module is in /etc/cobbler/modules.conf\n\nCopyright 2007-2009, Red Hat, Inc and Others\nMichael DeHaan <michael.dehaan AT gmail>\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n02110-1301  USA\n\nPAM python code based on the pam_python code created by Chris AtLee:\nhttp://atlee.ca/software/pam/\n\n#-----------------------------------------------\npam_python (c) 2007 Chris AtLee <chris@atlee.ca>\nLicensed under the MIT license:\nhttp://www.opensource.org/licenses/mit-license.php\n\nPAM module for python\n\nProvides an authenticate function that will allow the caller to authenticate\na user against the Pluggable Authentication Modules (PAM) on the system.\n\nImplemented using ctypes, so no compilation is necessary.\n\"\"\"\n\nfrom ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, pointer, sizeof\nfrom ctypes import c_void_p, c_uint, c_char_p, c_char, c_int\nfrom ctypes.util import find_library\n\nLIBPAM = CDLL(find_library(\"pam\"))\nLIBC = CDLL(find_library(\"c\"))\n\nCALLOC = LIBC.calloc\nCALLOC.restype = c_void_p\nCALLOC.argtypes = [c_uint, c_uint]\n\nSTRDUP = LIBC.strdup\nSTRDUP.argstypes = [c_char_p]\nSTRDUP.restype = POINTER(c_char)        # NOT c_char_p !!!!\n\n# Various constants\nPAM_PROMPT_ECHO_OFF = 1\nPAM_PROMPT_ECHO_ON = 2\nPAM_ERROR_MSG = 3\nPAM_TEXT_INFO = 4\n\n\ndef register() -> str:\n    \"\"\"\n    The mandatory Cobbler module registration hook.\n    \"\"\"\n    return \"authn\"\n\n\nclass PamHandle(Structure):\n    \"\"\"\n    wrapper class for pam_handle_t\n    \"\"\"\n    _fields_ = [(\"handle\", c_void_p)]\n\n    def __init__(self):\n        Structure.__init__(self)\n        self.handle = 0\n\n\nclass PamMessage(Structure):\n    \"\"\"\n    wrapper class for pam_message structure\n    \"\"\"\n    _fields_ = [(\"msg_style\", c_int), (\"msg\", c_char_p)]\n\n    def __repr__(self):\n        return \"<PamMessage %i '%s'>\" % (self.msg_style, self.msg)\n\n\nclass PamResponse(Structure):\n    \"\"\"\n    wrapper class for pam_response structure\n    \"\"\"\n    _fields_ = [(\"resp\", c_char_p), (\"resp_retcode\", c_int)]\n\n    def __repr__(self):\n        return \"<PamResponse %i '%s'>\" % (self.resp_retcode, self.resp)\n\n\nCONV_FUNC = CFUNCTYPE(c_int, c_int, POINTER(POINTER(PamMessage)), POINTER(POINTER(PamResponse)), c_void_p)\n\n\nclass PamConv(Structure):\n    \"\"\"\n    wrapper class for pam_conv structure\n    \"\"\"\n    _fields_ = [(\"conv\", CONV_FUNC), (\"appdata_ptr\", c_void_p)]\n\n\nPAM_START = LIBPAM.pam_start\nPAM_START.restype = c_int\nPAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)]\n\nPAM_AUTHENTICATE = LIBPAM.pam_authenticate\nPAM_AUTHENTICATE.restype = c_int\nPAM_AUTHENTICATE.argtypes = [PamHandle, c_int]\n\n\ndef authenticate(api_handle, username: str, password: str) -> bool:\n    \"\"\"\n    :param api_handle: Used for resolving the the pam service name and getting the Logger.\n    :param username:The username to log in with.\n    :param password: The password to log in with.\n    :returns: True if the given username and password authenticate for the given service. Otherwise False\n    \"\"\"\n\n    @CONV_FUNC\n    def my_conv(n_messages, messages, p_response, app_data):\n        \"\"\"\n        Simple conversation function that responds to any prompt where the echo is off with the supplied password\n        \"\"\"\n        # Create an array of n_messages response objects\n        addr = CALLOC(n_messages, sizeof(PamResponse))\n        p_response[0] = cast(addr, POINTER(PamResponse))\n        for i in range(n_messages):\n            if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:\n                pw_copy = STRDUP(password.encode())\n                p_response.contents[i].resp = cast(pw_copy, c_char_p)\n                p_response.contents[i].resp_retcode = 0\n        return 0\n\n    try:\n        service = api_handle.settings().authn_pam_service\n    except:\n        service = 'login'\n\n    api_handle.logger.debug(\"authn_pam: PAM service is %s\" % service)\n\n    handle = PamHandle()\n    conv = PamConv(my_conv, 0)\n    retval = PAM_START(service.encode(), username.encode(), pointer(conv), pointer(handle))\n\n    if retval != 0:\n        # TODO: This is not an authentication error, something has gone wrong starting up PAM\n        api_handle.logger.error(\"authn_pam: error initializing PAM library\")\n        return False\n\n    retval = PAM_AUTHENTICATE(handle, 0)\n    return retval == 0\n", "path": "cobbler/modules/authentication/pam.py"}], "after_files": [{"content": "\"\"\"\nAuthentication module that uses /etc/cobbler/auth.conf\nChoice of authentication module is in /etc/cobbler/modules.conf\n\nCopyright 2007-2009, Red Hat, Inc and Others\nMichael DeHaan <michael.dehaan AT gmail>\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n02110-1301  USA\n\nPAM python code based on the pam_python code created by Chris AtLee:\nhttp://atlee.ca/software/pam/\n\n#-----------------------------------------------\npam_python (c) 2007 Chris AtLee <chris@atlee.ca>\nLicensed under the MIT license:\nhttp://www.opensource.org/licenses/mit-license.php\n\nPAM module for python\n\nProvides an authenticate function that will allow the caller to authenticate\na user against the Pluggable Authentication Modules (PAM) on the system.\n\nImplemented using ctypes, so no compilation is necessary.\n\"\"\"\n\nfrom ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, pointer, sizeof\nfrom ctypes import c_void_p, c_uint, c_char_p, c_char, c_int\nfrom ctypes.util import find_library\n\nLIBPAM = CDLL(find_library(\"pam\"))\nLIBC = CDLL(find_library(\"c\"))\n\nCALLOC = LIBC.calloc\nCALLOC.restype = c_void_p\nCALLOC.argtypes = [c_uint, c_uint]\n\nSTRDUP = LIBC.strdup\nSTRDUP.argstypes = [c_char_p]\nSTRDUP.restype = POINTER(c_char)        # NOT c_char_p !!!!\n\n# Various constants\nPAM_PROMPT_ECHO_OFF = 1\nPAM_PROMPT_ECHO_ON = 2\nPAM_ERROR_MSG = 3\nPAM_TEXT_INFO = 4\n\n\ndef register() -> str:\n    \"\"\"\n    The mandatory Cobbler module registration hook.\n    \"\"\"\n    return \"authn\"\n\n\nclass PamHandle(Structure):\n    \"\"\"\n    wrapper class for pam_handle_t\n    \"\"\"\n    _fields_ = [(\"handle\", c_void_p)]\n\n    def __init__(self):\n        Structure.__init__(self)\n        self.handle = 0\n\n\nclass PamMessage(Structure):\n    \"\"\"\n    wrapper class for pam_message structure\n    \"\"\"\n    _fields_ = [(\"msg_style\", c_int), (\"msg\", c_char_p)]\n\n    def __repr__(self):\n        return \"<PamMessage %i '%s'>\" % (self.msg_style, self.msg)\n\n\nclass PamResponse(Structure):\n    \"\"\"\n    wrapper class for pam_response structure\n    \"\"\"\n    _fields_ = [(\"resp\", c_char_p), (\"resp_retcode\", c_int)]\n\n    def __repr__(self):\n        return \"<PamResponse %i '%s'>\" % (self.resp_retcode, self.resp)\n\n\nCONV_FUNC = CFUNCTYPE(c_int, c_int, POINTER(POINTER(PamMessage)), POINTER(POINTER(PamResponse)), c_void_p)\n\n\nclass PamConv(Structure):\n    \"\"\"\n    wrapper class for pam_conv structure\n    \"\"\"\n    _fields_ = [(\"conv\", CONV_FUNC), (\"appdata_ptr\", c_void_p)]\n\n\nPAM_START = LIBPAM.pam_start\nPAM_START.restype = c_int\nPAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)]\n\nPAM_AUTHENTICATE = LIBPAM.pam_authenticate\nPAM_AUTHENTICATE.restype = c_int\nPAM_AUTHENTICATE.argtypes = [PamHandle, c_int]\n\nPAM_ACCT_MGMT = LIBPAM.pam_acct_mgmt\nPAM_ACCT_MGMT.restype = c_int\nPAM_ACCT_MGMT.argtypes = [PamHandle, c_int]\n\n\ndef authenticate(api_handle, username: str, password: str) -> bool:\n    \"\"\"\n    :param api_handle: Used for resolving the the pam service name and getting the Logger.\n    :param username:The username to log in with.\n    :param password: The password to log in with.\n    :returns: True if the given username and password authenticate for the given service. Otherwise False\n    \"\"\"\n\n    @CONV_FUNC\n    def my_conv(n_messages, messages, p_response, app_data):\n        \"\"\"\n        Simple conversation function that responds to any prompt where the echo is off with the supplied password\n        \"\"\"\n        # Create an array of n_messages response objects\n        addr = CALLOC(n_messages, sizeof(PamResponse))\n        p_response[0] = cast(addr, POINTER(PamResponse))\n        for i in range(n_messages):\n            if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:\n                pw_copy = STRDUP(password.encode())\n                p_response.contents[i].resp = cast(pw_copy, c_char_p)\n                p_response.contents[i].resp_retcode = 0\n        return 0\n\n    try:\n        service = api_handle.settings().authn_pam_service\n    except:\n        service = 'login'\n\n    api_handle.logger.debug(\"authn_pam: PAM service is %s\" % service)\n\n    handle = PamHandle()\n    conv = PamConv(my_conv, 0)\n    retval = PAM_START(service.encode(), username.encode(), pointer(conv), pointer(handle))\n\n    if retval != 0:\n        # TODO: This is not an authentication error, something has gone wrong starting up PAM\n        api_handle.logger.error(\"authn_pam: error initializing PAM library\")\n        return False\n\n    retval = PAM_AUTHENTICATE(handle, 0)\n\n    if retval == 0:\n        retval = PAM_ACCT_MGMT(handle, 0)\n\n    return retval == 0\n", "path": "cobbler/modules/authentication/pam.py"}]}