diff options
Diffstat (limited to 'security/cyrus-sasl2/files/pwcheck_pam.c')
-rw-r--r-- | security/cyrus-sasl2/files/pwcheck_pam.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/security/cyrus-sasl2/files/pwcheck_pam.c b/security/cyrus-sasl2/files/pwcheck_pam.c new file mode 100644 index 000000000000..57e1076ca92a --- /dev/null +++ b/security/cyrus-sasl2/files/pwcheck_pam.c @@ -0,0 +1,101 @@ + +#include <security/pam_appl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Static variables used to communicate between the conversation function + * and the server_login function + */ +static char *PAM_username; +static char *PAM_password; + +/* PAM conversation function + */ +static int PAM_conv (int num_msg, + const struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) { + int replies = 0; + struct pam_response *reply = NULL; + + #define COPY_STRING(s) (s) ? strdup(s) : NULL + + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) return PAM_CONV_ERR; + + for (replies = 0; replies < num_msg; replies++) { + switch (msg[replies]->msg_style) { + case PAM_PROMPT_ECHO_ON: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = COPY_STRING(PAM_username); + /* PAM frees resp */ + break; + case PAM_PROMPT_ECHO_OFF: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = COPY_STRING(PAM_password); + /* PAM frees resp */ + break; + case PAM_TEXT_INFO: + /* fall through */ + case PAM_ERROR_MSG: + /* ignore it, but pam still wants a NULL response... */ + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; + break; + default: + /* Must be an error of some sort... */ + free (reply); + return PAM_CONV_ERR; + } + } + *resp = reply; + return PAM_SUCCESS; +} + +static struct pam_conv PAM_conversation = { + PAM_conv, + NULL +}; + +/* Server log in + * Accepts: user name string + * password string + * Returns: "OK" if password validated, error message otherwise + */ + +char *pwcheck(char *username, char *password) +{ + pam_handle_t *pamh; + int pam_error; + + /* PAM only handles authentication, not user information. */ + if ( !(username && password && strlen(username) && strlen(password)) ) + return "Incorrect username"; + + /* validate password */ + + PAM_password = password; + PAM_username = username; + fprintf(stderr, "checking %s\n", username); + pam_error = pam_start("cyrus", username, &PAM_conversation, &pamh); + if (pam_error == PAM_SUCCESS) + pam_error = pam_authenticate(pamh, 0); + + if (pam_error == PAM_SUCCESS) + pam_error = pam_acct_mgmt(pamh, 0); + + if ( pam_error == PAM_SUCCESS) + fprintf(stderr, "\tauthenticated %s\n", username); + else + fprintf(stderr, "\tfailed to authenticate %s\n", username); + + if(pam_end(pamh, pam_error) != PAM_SUCCESS) { + pamh = NULL; + fprintf(stderr, "pwcheck: failed to release authenticator\n"); + exit(1); + } + return ( pam_error == PAM_SUCCESS ? "OK" : "Incorrect passwd" ); +} + + |