static pam_handle_t *sshpam_handle = NULL;
static int sshpam_err = 0;
static int sshpam_authenticated = 0;
-static int sshpam_new_authtok_reqd = 0;
static int sshpam_session_open = 0;
static int sshpam_cred_established = 0;
static int sshpam_account_status = -1;
static char **sshpam_env = NULL;
+static int *force_pwchange;
/* Some PAM implementations don't implement this */
#ifndef HAVE_PAM_GETENVLIST
void
pam_password_change_required(int reqd)
{
- sshpam_new_authtok_reqd = reqd;
+ debug3("%s %d", __func__, reqd);
+ *force_pwchange = reqd;
if (reqd) {
no_port_forwarding_flag |= 2;
no_agent_forwarding_flag |= 2;
no_port_forwarding_flag &= ~2;
no_agent_forwarding_flag &= ~2;
no_x11_forwarding_flag &= ~2;
-
}
}
+
/* Import regular and PAM environment from subprocess */
static void
import_environments(Buffer *b)
u_int i, num_env;
int err;
+ debug3("PAM: %s entering", __func__);
+
/* Import variables set by do_pam_account */
sshpam_account_status = buffer_get_int(b);
pam_password_change_required(buffer_get_int(b));
struct pam_response *reply;
int i;
+ debug3("PAM: %s entering, %d messages", __func__, n);
*resp = NULL;
ctxt = data;
if (compat20) {
if (!do_pam_account())
goto auth_fail;
- if (sshpam_new_authtok_reqd) {
+ if (*force_pwchange) {
sshpam_err = pam_chauthtok(sshpam_handle,
PAM_CHANGE_EXPIRED_AUTHTOK);
if (sshpam_err != PAM_SUCCESS)
#ifndef USE_POSIX_THREADS
/* Export variables set by do_pam_account */
buffer_put_int(&buffer, sshpam_account_status);
- buffer_put_int(&buffer, sshpam_new_authtok_reqd);
+ buffer_put_int(&buffer, *force_pwchange);
/* Export any environment strings set in child */
for(i = 0; environ[i] != NULL; i++)
{
struct pam_ctxt *ctxt = cleanup_ctxt;
+ debug3("PAM: %s entering", __func__);
if (ctxt != NULL && ctxt->pam_thread != 0) {
pthread_cancel(ctxt->pam_thread);
pthread_join(ctxt->pam_thread, NULL);
sshpam_null_conv(int n, const struct pam_message **msg,
struct pam_response **resp, void *data)
{
+ debug3("PAM: %s entering, %d messages", __func__, n);
return (PAM_CONV_ERR);
}
pam_close_session(sshpam_handle, PAM_SILENT);
sshpam_session_open = 0;
}
- sshpam_authenticated = sshpam_new_authtok_reqd = 0;
+ sshpam_authenticated = 0;
pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
}
struct pam_ctxt *ctxt;
int socks[2];
+ debug3("PAM: %s entering", __func__);
/* Refuse to start if we don't have PAM enabled */
if (!options.use_pam)
return NULL;
ctxt = xmalloc(sizeof *ctxt);
memset(ctxt, 0, sizeof(*ctxt));
+ force_pwchange = &(authctxt->force_pwchange);
+
/* Start the authentication thread */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
error("PAM: failed create sockets: %s", strerror(errno));
char *msg;
size_t len;
+ debug3("PAM: %s entering", __func__);
buffer_init(&buffer);
*name = xstrdup("");
*info = xstrdup("");
Buffer buffer;
struct pam_ctxt *ctxt = ctx;
- debug2("PAM: %s", __func__);
+ debug2("PAM: %s entering, %d responses", __func__, num);
switch (ctxt->pam_done) {
case 1:
sshpam_authenticated = 1;
{
struct pam_ctxt *ctxt = ctxtp;
+ debug3("PAM: %s entering", __func__);
sshpam_thread_cleanup();
xfree(ctxt);
/*
return (sshpam_account_status);
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
- debug3("%s: pam_acct_mgmt = %d", __func__, sshpam_err);
+ debug3("PAM: %s pam_acct_mgmt = %d", __func__, sshpam_err);
if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
sshpam_account_status = 0;
pam_strerror(sshpam_handle, sshpam_err));
}
-int
-is_pam_password_change_required(void)
-{
- return (sshpam_new_authtok_reqd);
-}
-
static int
pam_tty_conv(int n, const struct pam_message **msg,
struct pam_response **resp, void *data)
struct pam_response *reply;
int i;
+ debug3("PAM: %s called with %d messages", __func__, n);
+
*resp = NULL;
if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
pam_strerror(sshpam_handle, sshpam_err));
}
+static int
+pam_store_conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
+{
+ struct pam_response *reply;
+ int i;
+ size_t len;
+
+ debug3("PAM: %s called with %d messages", __func__, n);
+ *resp = NULL;
+
+ if (n <= 0 || n > PAM_MAX_NUM_MSG)
+ return (PAM_CONV_ERR);
+
+ if ((reply = malloc(n * sizeof(*reply))) == NULL)
+ return (PAM_CONV_ERR);
+ memset(reply, 0, n * sizeof(*reply));
+
+ for (i = 0; i < n; ++i) {
+ switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ len = strlen(PAM_MSG_MEMBER(msg, i, msg));
+ buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
+ buffer_append(&loginmsg, "\n", 1 );
+ reply[i].resp_retcode = PAM_SUCCESS;
+ break;
+ default:
+ goto fail;
+ }
+ }
+ *resp = reply;
+ return (PAM_SUCCESS);
+
+ fail:
+ for(i = 0; i < n; i++) {
+ if (reply[i].resp != NULL)
+ xfree(reply[i].resp);
+ }
+ xfree(reply);
+ return (PAM_CONV_ERR);
+}
+
+static struct pam_conv store_conv = { pam_store_conv, NULL };
+
void
do_pam_session(void)
{
+ debug3("PAM: opening session");
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
- (const void *)&tty_conv);
+ (const void *)&store_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
return (ret);
}
-void
-print_pam_messages(void)
-{
- /* XXX */
-}
-
char **
fetch_pam_child_environment(void)
{