diff options
author | Damien Miller <djm@mindrot.org> | 1999-12-30 15:08:44 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-12-30 15:08:44 +1100 |
commit | e72b7af17e519eb1d433b5119ef551f2584f8be6 (patch) | |
tree | 7ebbc8fefdfcfd9669dbe05718b142996df69a85 /auth-pam.c | |
parent | ece22a8312357e1f34916659d77fa7dd8d15ae32 (diff) |
- Removed most of the pam code into its own file auth-pam.[ch]. This
cleaned up sshd.c up significantly.
- Several other cleanups
Diffstat (limited to 'auth-pam.c')
-rw-r--r-- | auth-pam.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/auth-pam.c b/auth-pam.c new file mode 100644 index 00000000..8d872689 --- /dev/null +++ b/auth-pam.c @@ -0,0 +1,239 @@ +/* + * Author: Damien Miller + * Copyright (c) 1999 Damien Miller <djm@mindrot.org> + * All rights reserved + * Created: Thursday December 30 1999 + * PAM authentication and session management code. + */ + +#include "includes.h" + +#ifdef USE_PAM +#include "ssh.h" +#include "xmalloc.h" +#include "servconf.h" + +RCSID("$Id: auth-pam.c,v 1.1 1999/12/30 04:11:25 damien Exp $"); + +/* Callbacks */ +static int pamconv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr); +void pam_cleanup_proc(void *context); + +/* module-local variables */ +static struct pam_conv conv = { + pamconv, + NULL +}; +static struct pam_handle_t *pamh = NULL; +static const char *pampasswd = NULL; +static char *pamconv_msg = NULL; + +/* PAM conversation function. This is really a kludge to get the password */ +/* into PAM and to pick up any messages generated by PAM into pamconv_msg */ +static int pamconv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + struct pam_response *reply; + int count; + size_t msg_len; + char *p; + + /* PAM will free this later */ + reply = malloc(num_msg * sizeof(*reply)); + if (reply == NULL) + return PAM_CONV_ERR; + + for(count = 0; count < num_msg; count++) { + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + if (pampasswd == NULL) { + free(reply); + return PAM_CONV_ERR; + } + reply[count].resp_retcode = PAM_SUCCESS; + reply[count].resp = xstrdup(pampasswd); + break; + + case PAM_TEXT_INFO: + reply[count].resp_retcode = PAM_SUCCESS; + reply[count].resp = xstrdup(""); + + if (msg[count]->msg == NULL) + break; + + debug("Adding PAM message: %s", msg[count]->msg); + + msg_len = strlen(msg[count]->msg); + if (pamconv_msg) { + size_t n = strlen(pamconv_msg); + pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2); + p = pamconv_msg + n; + } else { + pamconv_msg = p = xmalloc(msg_len + 2); + } + memcpy(p, msg[count]->msg, msg_len); + p[msg_len] = '\n'; + p[msg_len + 1] = '\0'; + break; + + case PAM_PROMPT_ECHO_ON: + case PAM_ERROR_MSG: + default: + free(reply); + return PAM_CONV_ERR; + } + } + + *resp = reply; + + return PAM_SUCCESS; +} + +/* Called at exit to cleanly shutdown PAM */ +void pam_cleanup_proc(void *context) +{ + int pam_retval; + + if (pamh != NULL) + { + pam_retval = pam_close_session((pam_handle_t *)pamh, 0); + if (pam_retval != PAM_SUCCESS) { + log("Cannot close PAM session: %.200s", + PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + + pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED); + if (pam_retval != PAM_SUCCESS) { + log("Cannot delete credentials: %.200s", + PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + + pam_retval = pam_end((pam_handle_t *)pamh, pam_retval); + if (pam_retval != PAM_SUCCESS) { + log("Cannot release PAM authentication: %.200s", + PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + } +} + +/* Attempt password authentation using PAM */ +int auth_pam_password(struct passwd *pw, const char *password) +{ + extern ServerOptions options; + int pam_retval; + + /* deny if no user. */ + if (pw == NULL) + return 0; + if (pw->pw_uid == 0 && options.permit_root_login == 2) + return 0; + if (*password == '\0' && options.permit_empty_passwd == 0) + return 0; + + pampasswd = password; + + pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); + if (pam_retval == PAM_SUCCESS) { + debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name); + return 1; + } else { + debug("PAM Password authentication for \"%.100s\" failed: %s", + pw->pw_name, PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + return 0; + } +} + +/* Do account management using PAM */ +int do_pam_account(char *username, char *remote_user) +{ + int pam_retval; + + debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname()); + pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST, + get_canonical_hostname()); + if (pam_retval != PAM_SUCCESS) { + fatal("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + + if (remote_user != NULL) { + debug("PAM setting ruser to \"%.200s\"", remote_user); + pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user); + if (pam_retval != PAM_SUCCESS) { + fatal("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + } + + pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0); + if (pam_retval != PAM_SUCCESS) { + log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + return(0); + } + + return(1); +} + +/* Do PAM-specific session initialisation */ +void do_pam_session(char *username, char *ttyname) +{ + int pam_retval; + + if (ttyname != NULL) { + debug("PAM setting tty to \"%.200s\"", ttyname); + pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + } + + pam_retval = pam_open_session((pam_handle_t *)pamh, 0); + if (pam_retval != PAM_SUCCESS) + fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); +} + +/* Set PAM credentials */ +void do_pam_setcred() +{ + int pam_retval; + + debug("PAM establishing creds"); + pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED); + if (pam_retval != PAM_SUCCESS) + fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); +} + +/* Cleanly shutdown PAM */ +void finish_pam(void) +{ + pam_cleanup_proc(NULL); + fatal_remove_cleanup(&pam_cleanup_proc, NULL); +} + +/* Start PAM authentication for specified account */ +void start_pam(struct passwd *pw) +{ + int pam_retval; + + debug("Starting up PAM with username \"%.200s\"", pw->pw_name); + + pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh); + if (pam_retval != PAM_SUCCESS) + fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); + + fatal_add_cleanup(&pam_cleanup_proc, NULL); +} + +/* Return list of PAM enviornment strings */ +char **fetch_pam_environment(void) +{ + return(pam_getenvlist((pam_handle_t *)pamh)); +} + +/* Print any messages that have been generated during authentication */ +/* or account checking to stderr */ +void print_pam_messages(void) +{ + if (pamconv_msg != NULL) + fprintf(stderr, pamconv_msg); +} + +#endif /* USE_PAM */ |