/* * ngx_auth_pam_talker: supply authentication information to PAM when asked * * Assumptions: * A password is asked for by requesting input without echoing * A username is asked for by requesting input _with_ echoing */ static int ngx_auth_pam_talker(int num_msg, const struct pam_message ** msg, struct pam_response ** resp, void *appdata_ptr) { int i; ngx_pam_userinfo *uinfo; struct pam_response *response; uinfo = (ngx_pam_userinfo *) appdata_ptr; response = NULL; /* parameter sanity checking */ if (!resp || !msg || !uinfo) return PAM_CONV_ERR; /* allocate memory to store response */ response = malloc(num_msg * sizeof(struct pam_response)); if (!response) return PAM_CONV_ERR; /* copy values */ for (i = 0; i < num_msg; i++) { /* initialize to safe values */ response[i].resp_retcode = 0; response[i].resp = 0; /* select response based on requested output style */ switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: /* on memory allocation failure, auth fails */ response[i].resp = strdup((const char *)uinfo->username.data); break; case PAM_PROMPT_ECHO_OFF: response[i].resp = strdup((const char *)uinfo->password.data); break; default: free_resp(i, response); return PAM_CONV_ERR; } } /* everything okay, set PAM response values */ *resp = response; return PAM_SUCCESS; }
/* ARGSUSED */ int pam_tty_conv(int num_msg, struct pam_message **mess, struct pam_response **resp, void *my_data) { struct pam_message *m = *mess; struct pam_response *r = calloc(num_msg, sizeof (struct pam_response)); int i; if (num_msg >= PAM_MAX_NUM_MSG) { (void) fprintf(stderr, "too many messages %d >= %d\n", num_msg, PAM_MAX_NUM_MSG); free(r); *resp = NULL; return (PAM_CONV_ERR); } /* Talk it out */ *resp = r; for (i = 0; i < num_msg; i++) { int echo_off; /* bad message from service module */ if (m->msg == NULL) { (void) fprintf(stderr, "message[%d]: %d/NULL\n", i, m->msg_style); goto err; } /* * fix up final newline: * removed for prompts * added back for messages */ if (m->msg[strlen(m->msg)] == '\n') m->msg[strlen(m->msg)] = '\0'; r->resp = NULL; r->resp_retcode = 0; echo_off = 0; switch (m->msg_style) { case PAM_PROMPT_ECHO_OFF: echo_off = 1; /*FALLTHROUGH*/ case PAM_PROMPT_ECHO_ON: (void) fputs(m->msg, stdout); r->resp = getinput(echo_off); break; case PAM_ERROR_MSG: (void) fputs(m->msg, stderr); (void) fputc('\n', stderr); break; case PAM_TEXT_INFO: (void) fputs(m->msg, stdout); (void) fputc('\n', stdout); break; default: (void) fprintf(stderr, "message[%d]: unknown type " "%d/val=\"%s\"\n", i, m->msg_style, m->msg); /* error, service module won't clean up */ goto err; } if (errno == EINTR) goto err; /* next message/response */ m++; r++; } return (PAM_SUCCESS); err: free_resp(i, r); *resp = NULL; return (PAM_CONV_ERR); }