4 * Heimdal compatibility layer.
6 * $FreeBSD: src/lib/libpam/modules/pam_krb5/compat_heimdal.c,v 1.1.2.2 2001/07/29 18:57:30 markm Exp $
7 * $DragonFly: src/lib/libpam/modules/pam_krb5/Attic/compat_heimdal.c,v 1.4 2004/10/25 19:38:45 drhodus Exp $
16 #include <security/pam_appl.h>
17 #include <security/pam_modules.h>
21 compat_princ_component(krb5_context context, krb5_principal princ, int n)
23 return princ->name.name_string.val[n];
27 compat_free_data_contents(krb5_context context, krb5_data *data)
29 krb5_xfree(data->data);
32 static krb5_error_code
33 heimdal_pam_prompter(krb5_context context, void *data, const char *name,
34 const char *banner, int num_prompts, krb5_prompt prompts[])
36 int pam_prompts = num_prompts;
39 struct pam_message *msg;
40 struct pam_response *resp = NULL;
41 struct pam_conv *conv;
42 pam_handle_t *pamh = (pam_handle_t *) data;
44 if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0)
45 return KRB5KRB_ERR_GENERIC;
50 msg = calloc(sizeof(struct pam_message) * pam_prompts, 1);
54 /* Now use pam_prompts as an index */
58 msg[pam_prompts].msg = malloc(strlen(banner) + 1);
59 if (!msg[pam_prompts].msg)
61 strcpy((char *) msg[pam_prompts].msg, banner);
62 msg[pam_prompts].msg_style = PAM_TEXT_INFO;
66 for (i = 0; i < num_prompts; i++) {
67 msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3);
68 if (!msg[pam_prompts].msg)
70 sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt);
71 msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF
76 if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg,
77 &resp, conv->appdata_ptr)) != 0)
83 /* Reuse pam_prompts as a starting index */
88 for (i = 0; i < num_prompts; i++, pam_prompts++) {
90 if (!resp[pam_prompts].resp) {
91 pamret = PAM_AUTH_ERR;
94 len = strlen(resp[pam_prompts].resp); /* Help out the compiler */
95 if (len > prompts[i].reply->length) {
96 pamret = PAM_AUTH_ERR;
99 memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len);
100 prompts[i].reply->length = len;
104 /* pam_prompts is correct at this point */
106 for (i = 0; i < pam_prompts; i++) {
108 free((char *) msg[i].msg);
113 for (i = 0; i < pam_prompts; i++) {
115 * Note that PAM is underspecified wrt free()'ing resp[i].resp.
116 * It's not clear if I should free it, or if the application
117 * has to. Therefore most (all?) apps won't free() it, and I
118 * can't either, as I am not sure it was malloc()'d. All PAM
119 * implementations I've seen leak memory here. Not so bad, IFF
120 * you fork/exec for each PAM authentication (as is typical).
127 /* This does not lose resp[i].resp if the application saved a copy. */
131 return (pamret ? KRB5KRB_ERR_GENERIC : 0);
134 krb5_prompter_fct pam_prompter = heimdal_pam_prompter;