static int sshpam_thread_status = -1;
static mysig_t sshpam_oldsig;
-static void
+static void
sshpam_sigchld_handler(int sig)
{
signal(SIGCHLD, SIG_DFL);
if (cleanup_ctxt == NULL)
return; /* handler called after PAM cleanup, shouldn't happen */
if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
- <= 0) {
+ <= 0) {
/* PAM thread has not exitted, privsep slave must have */
kill(cleanup_ctxt->pam_thread, SIGTERM);
if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
void *(*thread_start)(void *), void *arg)
{
pid_t pid;
+ struct pam_ctxt *ctx = arg;
sshpam_thread_status = -1;
switch ((pid = fork())) {
error("fork(): %s", strerror(errno));
return (-1);
case 0:
+ close(ctx->pam_psock);
+ ctx->pam_psock = -1;
thread_start(arg);
_exit(1);
default:
*thread = pid;
+ close(ctx->pam_csock);
+ ctx->pam_csock = -1;
sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
return (0);
}
plen++;
xfree(msg);
break;
- case PAM_SUCCESS:
case PAM_AUTH_ERR:
+ debug3("PAM: PAM_AUTH_ERR");
+ if (**prompts != NULL && strlen(**prompts) != 0) {
+ *info = **prompts;
+ **prompts = NULL;
+ *num = 0;
+ **echo_on = 0;
+ ctxt->pam_done = -1;
+ return 0;
+ }
+ /* FALLTHROUGH */
+ case PAM_SUCCESS:
if (**prompts != NULL) {
/* drain any accumulated messages */
debug("PAM: %s", **prompts);
Buffer buffer;
struct pam_ctxt *ctxt = ctx;
- debug2("PAM: %s entering, %d responses", __func__, num);
+ debug2("PAM: %s entering, %u responses", __func__, num);
switch (ctxt->pam_done) {
case 1:
sshpam_authenticated = 1;
buffer_init(&buffer);
if (sshpam_authctxt->valid &&
(sshpam_authctxt->pw->pw_uid != 0 ||
- options.permit_root_login == PERMIT_YES))
+ options.permit_root_login == PERMIT_YES))
buffer_put_cstring(&buffer, *resp);
else
buffer_put_cstring(&buffer, badpw);
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
pam_strerror(sshpam_handle, sshpam_err));
-
+
if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
sshpam_account_status = 0;
return (sshpam_account_status);
*resp = reply;
return (PAM_SUCCESS);
- fail:
+ fail:
for(i = 0; i < n; i++) {
if (reply[i].resp != NULL)
xfree(reply[i].resp);
* information via timing (eg if the PAM config has a delay on fail).
*/
if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
- options.permit_root_login != PERMIT_YES))
+ options.permit_root_login != PERMIT_YES))
sshpam_password = badpw;
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
debug("PAM: password authentication accepted for %.100s",
authctxt->user);
- return 1;
+ return 1;
} else {
debug("PAM: password authentication failed for %.100s: %s",
authctxt->valid ? authctxt->user : "an illegal user",