This commit is contained in:
Jacques Vidrine 2000-11-06 19:56:21 +00:00
parent 06bce9d9d7
commit 85af8c73f2
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=34855
6 changed files with 400 additions and 116 deletions

View file

@ -1,6 +1,6 @@
--- Makefile.orig Tue Jan 4 19:08:51 2000
+++ Makefile Mon Nov 6 10:59:16 2000
@@ -1,48 +1,51 @@
+++ Makefile Mon Nov 6 13:44:54 2000
@@ -1,46 +1,49 @@
#
# Makefile for pam_krb5
#
@ -68,22 +68,17 @@
- rm -f *.so.1 *.o
+ rm -f *.so *.o
-pam_krb5_auth.o: pam_krb5_auth.c pam_krb5.h
+pam_krb5_auth.o: pam_krb5_auth.c pam_krb5.h krb5compat.h
pam_krb5_auth.o: pam_krb5_auth.c pam_krb5.h
$(CC) -c $(CFLAGS) $(INC) $<
@@ -55,5 +58,11 @@
$(CC) -c $(CFLAGS) $(INC) $<
pam_krb5_pass.o: pam_krb5_pass.c pam_krb5.h
@@ -54,6 +57,12 @@
pam_krb5_sess.o: pam_krb5_sess.c pam_krb5.h
$(CC) -c $(CFLAGS) $(INC) $<
-support.o: support.c pam_krb5.h
+support.o: support.c pam_krb5.h krb5compat.h
support.o: support.c pam_krb5.h
+ $(CC) -c $(CFLAGS) $(INC) $<
+
+compat_heimdal.o: compat_heimdal.c krb5compat.h
+compat_heimdal.o: compat_heimdal.c
+ $(CC) -c $(CFLAGS) $(INC) $<
+
+compat_mit.o: compat_mit.c krb5compat.h
+compat_mit.o: compat_mit.c
$(CC) -c $(CFLAGS) $(INC) $<

View file

@ -1,10 +1,23 @@
--- pam_krb5.h.orig Tue Jan 4 19:08:51 2000
+++ pam_krb5.h Mon Nov 6 10:21:49 2000
@@ -6,6 +6,6 @@
+++ pam_krb5.h Mon Nov 6 13:42:22 2000
@@ -5,7 +5,18 @@
*/
int get_user_info(pam_handle_t *, char *, int, char **);
krb5_error_code pam_prompter(krb5_context, void *, const char *,
-krb5_error_code pam_prompter(krb5_context, void *, const char *,
- const char *, int, krb5_prompt[]);
+ int, krb5_prompt[]);
int verify_krb_v5_tgt(krb5_context, krb5_ccache, int);
void cleanup_cache(pam_handle_t *, void *, int);
+
+krb5_prompter_fct pam_prompter;
+
+const char *compat_princ_component(krb5_context, krb5_principal, int);
+void compat_free_data_contents(krb5_context, krb5_data *);
+krb5_error_code compat_cc_next_cred(krb5_context, const krb5_ccache,
+ krb5_cc_cursor *, krb5_creds *);
+
+#ifndef ENCTYPE_DES_CBC_MD5
+#define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5
+#endif
+
+

View file

@ -1,5 +1,5 @@
--- pam_krb5_auth.c.orig Tue Jan 4 19:08:51 2000
+++ pam_krb5_auth.c Mon Nov 6 10:46:08 2000
+++ pam_krb5_auth.c Mon Nov 6 13:45:48 2000
@@ -7,9 +7,11 @@
static const char rcsid[] = "$Id: pam_krb5_auth.c,v 1.18 2000/01/04 08:44:08 fcusack Exp $";
@ -12,17 +12,15 @@
#include <strings.h> /* strchr */
#include <syslog.h> /* syslog */
#include <unistd.h> /* chown */
@@ -19,7 +21,9 @@
@@ -19,6 +21,7 @@
#include <security/pam_modules.h>
#include <krb5.h>
+#include <com_err.h>
#include "pam_krb5.h"
+#include "krb5compat.h"
extern krb5_cc_ops krb5_mcc_ops;
@@ -42,7 +46,7 @@
@@ -42,7 +45,7 @@
krb5_get_init_creds_opt opts;
int pamret, i;
@ -31,7 +29,7 @@
char *princ_name = NULL;
char *pass = NULL, *service = NULL;
char *prompt = NULL;
@@ -74,13 +78,13 @@
@@ -74,13 +77,13 @@
}
/* Get service name */
@ -47,7 +45,7 @@
DLOG("krb5_init_context()", error_message(krbret));
return PAM_SERVICE_ERR;
}
@@ -93,7 +97,7 @@
@@ -93,7 +96,7 @@
krb5_get_init_creds_opt_set_forwardable(&opts, 1);
/* For CNS */
@ -56,7 +54,7 @@
/* Solaris dtlogin doesn't call pam_end() on failure */
if (krbret != KRB5_CC_TYPE_EXISTS) {
DLOG("krb5_cc_register()", error_message(krbret));
@@ -103,14 +107,14 @@
@@ -103,14 +106,14 @@
}
/* Get principal name */
@ -73,7 +71,7 @@
DLOG("krb5_unparse_name()", error_message(krbret));
pamret = PAM_SERVICE_ERR;
goto cleanup2;
@@ -126,18 +130,19 @@
@@ -126,18 +129,19 @@
(void) sprintf(prompt, "Password for %s: ", princ_name);
if (try_first_pass || use_first_pass)
@ -96,7 +94,7 @@
DLOG("pam_set_item()", pam_strerror(pamh, pamret));
free(pass);
pamret = PAM_SERVICE_ERR;
@@ -145,25 +150,26 @@
@@ -145,25 +149,26 @@
}
free(pass);
/* Now we get it back from the library. */
@ -128,7 +126,7 @@
DLOG("pam_get_item()", pam_strerror(pamh, pamret));
pamret = PAM_SERVICE_ERR;
goto cleanup2;
@@ -177,9 +183,8 @@
@@ -177,9 +182,8 @@
}
/* Get a TGT */
@ -140,7 +138,7 @@
DLOG("krb5_get_init_creds_password()", error_message(krbret));
if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
pass = NULL;
@@ -193,17 +198,17 @@
@@ -193,17 +197,17 @@
strcpy(cache_name, "MEMORY:");
(void) tmpnam(&cache_name[7]);
@ -161,7 +159,7 @@
DLOG("krb5_cc_store_cred()", error_message(krbret));
(void) krb5_cc_destroy(pam_context, ccache);
pamret = PAM_SERVICE_ERR;
@@ -224,7 +229,7 @@
@@ -224,7 +228,7 @@
pamret = PAM_AUTH_ERR;
goto cleanup;
}
@ -170,7 +168,7 @@
DLOG("pam_set_data()", pam_strerror(pamh, pamret));
(void) krb5_cc_destroy(pam_context, ccache);
pamret = PAM_SERVICE_ERR;
@@ -288,22 +293,22 @@
@@ -288,22 +292,22 @@
else if (strcmp(argv[i], "no_ccache") == 0)
return PAM_SUCCESS;
else if (strstr(argv[i], "ccache=") == argv[i])
@ -197,7 +195,7 @@
DLOG("krb5_init_context()", error_message(krbret));
return PAM_SERVICE_ERR;
}
@@ -311,7 +316,8 @@
@@ -311,7 +315,8 @@
euid = geteuid(); /* Usually 0 */
/* Retrieve the cache name */
@ -207,7 +205,7 @@
DLOG("pam_get_data()", pam_strerror(pamh, pamret));
pamret = PAM_CRED_UNAVAIL;
goto cleanup3;
@@ -340,7 +346,7 @@
@@ -340,7 +345,7 @@
pamret = PAM_BUF_ERR;
goto cleanup3;
}
@ -216,7 +214,7 @@
} else {
/* cache_name was supplied */
char *p = calloc(PATH_MAX + 10, 1); /* should be plenty */
@@ -357,10 +363,10 @@
@@ -357,10 +362,10 @@
if (*q == '%') {
q++;
if (*q == 'u') {
@ -229,7 +227,7 @@
p += strlen(p);
} else {
/* Not a special token */
@@ -375,24 +381,27 @@
@@ -375,24 +380,27 @@
}
/* Initialize the new ccache */
@ -261,7 +259,7 @@
DLOG("krb5_cc_start_seq_get()", error_message(krbret));
(void) krb5_cc_destroy(pam_context, ccache_perm);
pamret = PAM_SERVICE_ERR;
@@ -400,9 +409,10 @@
@@ -400,9 +408,10 @@
}
/* Copy the creds (should be two of them) */
@ -275,7 +273,7 @@
DLOG("krb5_cc_store_cred()", error_message(krbret));
(void) krb5_cc_destroy(pam_context, ccache_perm);
krb5_free_cred_contents(pam_context, &creds);
@@ -432,7 +442,7 @@
@@ -432,7 +441,7 @@
}
sprintf(cache_env_name, "KRB5CCNAME=%s", cache_name);

View file

@ -1,6 +1,6 @@
--- support.c.orig Tue Jan 4 19:08:51 2000
+++ support.c Mon Nov 6 11:55:47 2000
@@ -6,12 +6,17 @@
+++ support.c Mon Nov 6 13:36:39 2000
@@ -6,11 +6,15 @@
static const char rcsid[] = "$Id: support.c,v 1.8 2000/01/04 09:50:03 fcusack Exp $";
@ -14,11 +14,9 @@
#include <krb5.h>
+#include <com_err.h>
#include "pam_krb5.h"
+#include "krb5compat.h"
/*
* Get info from the user. Disallow null responses (regardless of flags).
@@ -22,11 +27,12 @@
@@ -22,11 +26,12 @@
get_user_info(pam_handle_t *pamh, char *prompt, int type, char **response)
{
int pamret;
@ -33,7 +31,7 @@
return pamret;
/* set up conversation call */
@@ -34,7 +40,7 @@
@@ -34,7 +39,7 @@
msg.msg_style = type;
msg.msg = prompt;
@ -42,35 +40,39 @@
return pamret;
/* Caller should ignore errors for non-response conversations */
@@ -53,8 +59,8 @@
@@ -51,124 +56,6 @@
return pamret;
}
krb5_error_code
-
-krb5_error_code
-pam_prompter(krb5_context context, void *data, const char *name,
- const char *banner, int num_prompts, krb5_prompt prompts[])
+pam_prompter(krb5_context context, void *data, const char *banner, int
+ num_prompts, krb5_prompt prompts[])
{
int pam_prompts = num_prompts;
int pamret, i;
@@ -64,12 +70,9 @@
struct pam_conv *conv;
pam_handle_t *pamh = (pam_handle_t *) data;
-{
- int pam_prompts = num_prompts;
- int pamret, i;
-
- struct pam_message *msg;
- struct pam_response *resp = NULL;
- struct pam_conv *conv;
- pam_handle_t *pamh = (pam_handle_t *) data;
-
- if (pamret = pam_get_item(pamh, PAM_CONV, (void **) &conv))
+ if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0)
return KRB5KRB_ERR_GENERIC;
- return KRB5KRB_ERR_GENERIC;
-
- if (name)
- pam_prompts++;
-
if (banner)
pam_prompts++;
@@ -80,21 +83,11 @@
/* Now use pam_prompts as an index */
pam_prompts = 0;
- if (banner)
- pam_prompts++;
-
- msg = calloc(sizeof(struct pam_message) * pam_prompts, 1);
- if (!msg)
- return ENOMEM;
-
- /* Now use pam_prompts as an index */
- pam_prompts = 0;
-
- /* Sigh. malloc all the prompts. */
- if (name) {
- msg[pam_prompts].msg = malloc(strlen(name) + 1);
@ -81,51 +83,89 @@
- pam_prompts++;
- }
-
if (banner) {
msg[pam_prompts].msg = malloc(strlen(banner) + 1);
if (!msg[pam_prompts].msg)
goto cleanup;
- if (banner) {
- msg[pam_prompts].msg = malloc(strlen(banner) + 1);
- if (!msg[pam_prompts].msg)
- goto cleanup;
- strcpy(msg[pam_prompts].msg, banner);
+ strcpy((char *) msg[pam_prompts].msg, banner);
msg[pam_prompts].msg_style = PAM_TEXT_INFO;
pam_prompts++;
}
@@ -103,13 +96,14 @@
msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3);
if (!msg[pam_prompts].msg)
goto cleanup;
- msg[pam_prompts].msg_style = PAM_TEXT_INFO;
- pam_prompts++;
- }
-
- for (i = 0; i < num_prompts; i++) {
- msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3);
- if (!msg[pam_prompts].msg)
- goto cleanup;
- sprintf(msg[pam_prompts].msg, "%s: ", prompts[i].prompt);
+ sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt);
msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF
: PAM_PROMPT_ECHO_ON;
pam_prompts++;
}
- msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF
- : PAM_PROMPT_ECHO_ON;
- pam_prompts++;
- }
-
- if (pamret = conv->conv(pam_prompts, &msg, &resp, conv->appdata_ptr))
+ if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg,
+ &resp, conv->appdata_ptr)) != 0)
goto cleanup;
if (!resp)
@@ -117,8 +111,6 @@
/* Reuse pam_prompts as a starting index */
pam_prompts = 0;
- goto cleanup;
-
- if (!resp)
- goto cleanup;
-
- /* Reuse pam_prompts as a starting index */
- pam_prompts = 0;
- if (name)
- pam_prompts++;
if (banner)
pam_prompts++;
@@ -142,7 +134,7 @@
for (i = 0; i < pam_prompts; i++) {
if (msg[i].msg)
- if (banner)
- pam_prompts++;
-
- for (i = 0; i < num_prompts; i++, pam_prompts++) {
- register int len;
- if (!resp[pam_prompts].resp) {
- pamret = PAM_AUTH_ERR;
- goto cleanup;
- }
- len = strlen(resp[pam_prompts].resp); /* Help out the compiler */
- if (len > prompts[i].reply->length) {
- pamret = PAM_AUTH_ERR;
- goto cleanup;
- }
- memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len);
- prompts[i].reply->length = len;
- }
-
-cleanup:
- /* pam_prompts is correct at this point */
-
- for (i = 0; i < pam_prompts; i++) {
- if (msg[i].msg)
- free(msg[i].msg);
+ free((char *) msg[i].msg);
}
free(msg);
@@ -189,8 +181,6 @@
- }
- free(msg);
-
- if (resp) {
- for (i = 0; i < pam_prompts; i++) {
- /*
- * Note that PAM is underspecified wrt free()'ing resp[i].resp.
- * It's not clear if I should free it, or if the application
- * has to. Therefore most (all?) apps won't free() it, and I
- * can't either, as I am not sure it was malloc()'d. All PAM
- * implementations I've seen leak memory here. Not so bad, IFF
- * you fork/exec for each PAM authentication (as is typical).
- */
-#if 0
- if (resp[i].resp)
- free(resp[i].resp);
-#endif /* 0 */
- }
- /* This does not lose resp[i].resp if the application saved a copy. */
- free(resp);
- }
-
- return (pamret ? KRB5KRB_ERR_GENERIC : 0);
-}
-
-
/*
* This routine with some modification is from the MIT V5B6 appl/bsd/login.c
*
@@ -189,8 +76,6 @@
krb5_keyblock * keyblock = 0;
krb5_data packet;
krb5_auth_context auth_context = NULL;
@ -134,7 +174,7 @@
packet.data = 0;
@@ -198,8 +188,8 @@
@@ -198,8 +83,8 @@
* Get the server principal for the local host.
* (Use defaults of "host" and canonicalized local name.)
*/
@ -145,7 +185,7 @@
if (debug)
syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s",
"krb5_sname_to_principal()", error_message(retval));
@@ -207,7 +197,7 @@
@@ -207,7 +92,7 @@
}
/* Extract the name directly. */
@ -154,7 +194,7 @@
phost[BUFSIZ - 1] = '\0';
/*
@@ -215,8 +205,8 @@
@@ -215,8 +100,8 @@
* (use default/configured keytab, kvno IGNORE_VNO to get the
* first match, and enctype is currently ignored anyhow.)
*/
@ -165,7 +205,7 @@
/* Keytab or service key does not exist */
if (debug)
syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s",
@@ -256,7 +246,7 @@
@@ -256,7 +141,7 @@
cleanup:
if (packet.data)

View file

@ -1,8 +1,15 @@
--- compat_heimdal.c.orig Mon Nov 6 10:21:49 2000
+++ compat_heimdal.c Mon Nov 6 10:48:37 2000
@@ -0,0 +1,21 @@
--- compat_heimdal.c.orig Mon Nov 6 13:27:02 2000
+++ compat_heimdal.c Mon Nov 6 13:43:10 2000
@@ -0,0 +1,133 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <krb5.h>
+#include "krb5compat.h"
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+#include "pam_krb5.h"
+
+const char *
+compat_princ_component(krb5_context context, krb5_principal princ, int n)
@ -22,3 +29,108 @@
+{
+ return krb5_cc_next_cred(context, id, creds, cursor);
+}
+
+
+static krb5_error_code
+heimdal_pam_prompter(krb5_context context, void *data, const char *banner, int
+ num_prompts, krb5_prompt prompts[])
+{
+ int pam_prompts = num_prompts;
+ int pamret, i;
+
+ struct pam_message *msg;
+ struct pam_response *resp = NULL;
+ struct pam_conv *conv;
+ pam_handle_t *pamh = (pam_handle_t *) data;
+
+ if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0)
+ return KRB5KRB_ERR_GENERIC;
+
+ if (banner)
+ pam_prompts++;
+
+ msg = calloc(sizeof(struct pam_message) * pam_prompts, 1);
+ if (!msg)
+ return ENOMEM;
+
+ /* Now use pam_prompts as an index */
+ pam_prompts = 0;
+
+ if (banner) {
+ msg[pam_prompts].msg = malloc(strlen(banner) + 1);
+ if (!msg[pam_prompts].msg)
+ goto cleanup;
+ strcpy((char *) msg[pam_prompts].msg, banner);
+ msg[pam_prompts].msg_style = PAM_TEXT_INFO;
+ pam_prompts++;
+ }
+
+ for (i = 0; i < num_prompts; i++) {
+ msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3);
+ if (!msg[pam_prompts].msg)
+ goto cleanup;
+ sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt);
+ msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF
+ : PAM_PROMPT_ECHO_ON;
+ pam_prompts++;
+ }
+
+ if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg,
+ &resp, conv->appdata_ptr)) != 0)
+ goto cleanup;
+
+ if (!resp)
+ goto cleanup;
+
+ /* Reuse pam_prompts as a starting index */
+ pam_prompts = 0;
+ if (banner)
+ pam_prompts++;
+
+ for (i = 0; i < num_prompts; i++, pam_prompts++) {
+ register int len;
+ if (!resp[pam_prompts].resp) {
+ pamret = PAM_AUTH_ERR;
+ goto cleanup;
+ }
+ len = strlen(resp[pam_prompts].resp); /* Help out the compiler */
+ if (len > prompts[i].reply->length) {
+ pamret = PAM_AUTH_ERR;
+ goto cleanup;
+ }
+ memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len);
+ prompts[i].reply->length = len;
+ }
+
+cleanup:
+ /* pam_prompts is correct at this point */
+
+ for (i = 0; i < pam_prompts; i++) {
+ if (msg[i].msg)
+ free((char *) msg[i].msg);
+ }
+ free(msg);
+
+ if (resp) {
+ for (i = 0; i < pam_prompts; i++) {
+ /*
+ * Note that PAM is underspecified wrt free()'ing resp[i].resp.
+ * It's not clear if I should free it, or if the application
+ * has to. Therefore most (all?) apps won't free() it, and I
+ * can't either, as I am not sure it was malloc()'d. All PAM
+ * implementations I've seen leak memory here. Not so bad, IFF
+ * you fork/exec for each PAM authentication (as is typical).
+ */
+#if 0
+ if (resp[i].resp)
+ free(resp[i].resp);
+#endif /* 0 */
+ }
+ /* This does not lose resp[i].resp if the application saved a copy. */
+ free(resp);
+ }
+
+ return (pamret ? KRB5KRB_ERR_GENERIC : 0);
+}
+
+krb5_prompter_fct pam_prompter = heimdal_pam_prompter;

View file

@ -1,8 +1,15 @@
--- compat_mit.c.orig Mon Nov 6 10:21:49 2000
+++ compat_mit.c Mon Nov 6 10:49:14 2000
@@ -0,0 +1,21 @@
--- compat_mit.c.orig Mon Nov 6 13:48:30 2000
+++ compat_mit.c Mon Nov 6 13:52:48 2000
@@ -0,0 +1,147 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <krb5.h>
+#include "krb5compat.h"
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+#include "pam_krb5.h"
+
+const char *
+compat_princ_component(krb5_context context, krb5_principal princ, int n)
@ -22,3 +29,122 @@
+{
+ return krb5_cc_next_cred(context, id, cursor, creds);
+}
+
+static krb5_error_code
+mit_pam_prompter(krb5_context context, void *data, const char *name,
+ const char *banner, int num_prompts, krb5_prompt prompts[])
+{
+ int pam_prompts = num_prompts;
+ int pamret, i;
+
+ struct pam_message *msg;
+ struct pam_response *resp = NULL;
+ struct pam_conv *conv;
+ pam_handle_t *pamh = (pam_handle_t *) data;
+
+ if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0)
+ return KRB5KRB_ERR_GENERIC;
+
+ if (name)
+ pam_prompts++;
+
+ if (banner)
+ pam_prompts++;
+
+ msg = calloc(sizeof(struct pam_message) * pam_prompts, 1);
+ if (!msg)
+ return ENOMEM;
+
+ /* Now use pam_prompts as an index */
+ pam_prompts = 0;
+
+ /* Sigh. malloc all the prompts. */
+ if (name) {
+ msg[pam_prompts].msg = malloc(strlen(name) + 1);
+ if (!msg[pam_prompts].msg)
+ goto cleanup;
+ strcpy((char *) msg[pam_prompts].msg, name);
+ msg[pam_prompts].msg_style = PAM_TEXT_INFO;
+ pam_prompts++;
+ }
+
+ if (banner) {
+ msg[pam_prompts].msg = malloc(strlen(banner) + 1);
+ if (!msg[pam_prompts].msg)
+ goto cleanup;
+ strcpy((char *) msg[pam_prompts].msg, banner);
+ msg[pam_prompts].msg_style = PAM_TEXT_INFO;
+ pam_prompts++;
+ }
+
+ for (i = 0; i < num_prompts; i++) {
+ msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3);
+ if (!msg[pam_prompts].msg)
+ goto cleanup;
+ sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt);
+ msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF
+ : PAM_PROMPT_ECHO_ON;
+ pam_prompts++;
+ }
+
+ if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg,
+ &resp, conv->appdata_ptr)) != 0)
+ goto cleanup;
+
+ if (!resp)
+ goto cleanup;
+
+ /* Reuse pam_prompts as a starting index */
+ pam_prompts = 0;
+ if (name)
+ pam_prompts++;
+ if (banner)
+ pam_prompts++;
+
+ for (i = 0; i < num_prompts; i++, pam_prompts++) {
+ register int len;
+ if (!resp[pam_prompts].resp) {
+ pamret = PAM_AUTH_ERR;
+ goto cleanup;
+ }
+ len = strlen(resp[pam_prompts].resp); /* Help out the compiler */
+ if (len > prompts[i].reply->length) {
+ pamret = PAM_AUTH_ERR;
+ goto cleanup;
+ }
+ memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len);
+ prompts[i].reply->length = len;
+ }
+
+cleanup:
+ /* pam_prompts is correct at this point */
+
+ for (i = 0; i < pam_prompts; i++) {
+ if (msg[i].msg)
+ free((char *) msg[i].msg);
+ }
+ free(msg);
+
+ if (resp) {
+ for (i = 0; i < pam_prompts; i++) {
+ /*
+ * Note that PAM is underspecified wrt free()'ing resp[i].resp.
+ * It's not clear if I should free it, or if the application
+ * has to. Therefore most (all?) apps won't free() it, and I
+ * can't either, as I am not sure it was malloc()'d. All PAM
+ * implementations I've seen leak memory here. Not so bad, IFF
+ * you fork/exec for each PAM authentication (as is typical).
+ */
+#if 0
+ if (resp[i].resp)
+ free(resp[i].resp);
+#endif /* 0 */
+ }
+ /* This does not lose resp[i].resp if the application saved a copy. */
+ free(resp);
+ }
+
+ return (pamret ? KRB5KRB_ERR_GENERIC : 0);
+}
+
+krb5_prompter_fct pam_prompter = mit_pam_prompter;