summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/ChangeLog4
-rw-r--r--src/src/auths/call_pam.c35
2 files changed, 23 insertions, 16 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 9f8775f0f..6a06e440f 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -24,6 +24,10 @@ JH/05 Regard command-line receipients as tainted.
JH/06 Bug 340: Remove the daemon pid file on exit, whe due to SIGTERM.
+JH/07 Bug 2489: Fix crash in the "pam" expansion condition. It seems that the
+ PAM library frees one of the arguments given to it, despite the
+ documentation. Therefore a plain malloc must be used.
+
Exim version 4.93
-----------------
diff --git a/src/src/auths/call_pam.c b/src/src/auths/call_pam.c
index 9a46b6b63..c96e146d1 100644
--- a/src/src/auths/call_pam.c
+++ b/src/src/auths/call_pam.c
@@ -69,9 +69,11 @@ pam_converse (int num_msg, PAM_CONVERSE_ARG2_TYPE **msg,
int sep = 0;
struct pam_response *reply;
-if (pam_arg_ended) return PAM_CONV_ERR;
+/* It seems that PAM frees reply[] */
-reply = store_get(sizeof(struct pam_response) * num_msg, FALSE);
+if ( pam_arg_ended
+ || !(reply = malloc(sizeof(struct pam_response) * num_msg)))
+ return PAM_CONV_ERR;
for (int i = 0; i < num_msg; i++)
{
@@ -80,25 +82,26 @@ for (int i = 0; i < num_msg; i++)
{
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
- arg = string_nextinlist(&pam_args, &sep, big_buffer, big_buffer_size);
- if (arg == NULL)
- {
- arg = US"";
- pam_arg_ended = TRUE;
- }
- reply[i].resp = CS string_copy_perm(arg, FALSE); /* PAM frees resp */
- reply[i].resp_retcode = PAM_SUCCESS;
- break;
+ arg = string_nextinlist(&pam_args, &sep, big_buffer, big_buffer_size);
+ if (!arg)
+ {
+ arg = US"";
+ pam_arg_ended = TRUE;
+ }
+ reply[i].resp = CS string_copy_malloc(arg); /* PAM frees resp */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ break;
case PAM_TEXT_INFO: /* Just acknowledge messages */
case PAM_ERROR_MSG:
- reply[i].resp_retcode = PAM_SUCCESS;
- reply[i].resp = NULL;
- break;
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = NULL;
+ break;
default: /* Must be an error of some sort... */
- pam_conv_had_error = TRUE;
- return PAM_CONV_ERR;
+ free(reply);
+ pam_conv_had_error = TRUE;
+ return PAM_CONV_ERR;
}
}