-/* $Cambridge: exim/src/src/auths/call_pam.c,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
is defined. However, some compilers don't like compiling empty modules, so keep
them happy with a dummy when skipping the rest. Make it reference itself to
stop picky compilers complaining that it is unused, and put in a dummy argument
-to stop even pickier compilers complaining about infinite loops. */
+to stop even pickier compilers complaining about infinite loops.
+Then use a mutually-recursive pair as gcc is just getting stupid. */
#ifndef SUPPORT_PAM
-static void dummy(int x) { dummy(x-1); }
+static void dummy(int x);
+static void dummy2(int x) { dummy(x-1); }
+static void dummy(int x) { dummy2(x-1); }
#else /* SUPPORT_PAM */
#ifdef PAM_H_IN_PAM
this to work on Solaris 2.6, so static variables are used instead. */
static int pam_conv_had_error;
-static uschar *pam_args;
+static const uschar *pam_args;
static BOOL pam_arg_ended;
pam_converse (int num_msg, PAM_CONVERSE_ARG2_TYPE **msg,
struct pam_response **resp, void *appdata_ptr)
{
-int i;
int sep = 0;
struct pam_response *reply;
-if (pam_arg_ended) return PAM_CONV_ERR;
-
-reply = malloc(sizeof(struct pam_response) * num_msg);
+/* It seems that PAM frees reply[] */
-if (reply == NULL) return PAM_CONV_ERR;
+if ( pam_arg_ended
+ || !(reply = malloc(sizeof(struct pam_response) * num_msg)))
+ return PAM_CONV_ERR;
-for (i = 0; i < num_msg; i++)
+for (int i = 0; i < num_msg; i++)
{
uschar *arg;
switch (msg[i]->msg_style)
{
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_malloc(arg); /* 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... */
- free (reply);
- pam_conv_had_error = TRUE;
- return PAM_CONV_ERR;
+ free(reply);
+ pam_conv_had_error = TRUE;
+ return PAM_CONV_ERR;
}
}
*/
int
-auth_call_pam(uschar *s, uschar **errptr)
+auth_call_pam(const uschar *s, uschar **errptr)
{
pam_handle_t *pamh = NULL;
struct pam_conv pamc;
return OK;
}
-*errptr = (uschar *)pam_strerror(pamh, pam_error);
+*errptr = US pam_strerror(pamh, pam_error);
DEBUG(D_auth) debug_printf("PAM error: %s\n", *errptr);
if (pam_error == PAM_USER_UNKNOWN ||