be our 'mysignal' by default. OK djm@
- (dtucker) [acconfig.h auth.c configure.ac sshd.8] Bug #422 again: deny
any access to locked accounts. ok djm@
+ - (djm) Bug #564: Perform PAM account checks for all authentications when
+ UsePAM=yes; ok dtucker
20030822
- (djm) s/get_progname/ssh_get_progname/g to avoid conflict with Heimdal
#include "servconf.h"
#include "ssh2.h"
#include "xmalloc.h"
+#include "auth-options.h"
extern ServerOptions options;
* Conversation function for authentication thread.
*/
static int
-sshpam_thread_conv(int n,
- const struct pam_message **msg,
- struct pam_response **resp,
- void *data)
+sshpam_thread_conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
{
Buffer buffer;
struct pam_ctxt *ctxt;
sshpam_err = pam_authenticate(sshpam_handle, 0);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
- sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
- if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD)
- goto auth_fail;
buffer_put_cstring(&buffer, "OK");
ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
buffer_free(&buffer);
}
static int
-sshpam_null_conv(int n,
- const struct pam_message **msg,
- struct pam_response **resp,
- void *data)
+sshpam_null_conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
{
-
return (PAM_CONV_ERR);
}
debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
if (sshpam_err != PAM_SUCCESS) {
- pam_end(sshpam_handle, sshpam_err);
+ pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
return (-1);
}
plen += snprintf(**prompts + plen, len, "%s", msg);
xfree(msg);
break;
- case PAM_NEW_AUTHTOK_REQD:
- sshpam_new_authtok_reqd = 1;
- /* FALLTHROUGH */
case PAM_SUCCESS:
case PAM_AUTH_ERR:
if (**prompts != NULL) {
sshpam_cleanup(NULL);
}
-int
-do_pam_account(const char *user, const char *ruser)
+u_int
+do_pam_account(void)
{
- /* XXX */
+ sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
+ debug3("%s: pam_acct_mgmt = %d", __func__, sshpam_err);
+
+ if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD)
+ return (0);
+
+ if (sshpam_err == PAM_NEW_AUTHTOK_REQD) {
+ sshpam_new_authtok_reqd = 1;
+
+ /* Prevent forwardings until password changed */
+ no_port_forwarding_flag |= 2;
+ no_agent_forwarding_flag |= 2;
+ no_x11_forwarding_flag |= 2;
+ }
+
return (1);
}
}
static int
-pam_chauthtok_conv(int n,
- const struct pam_message **msg,
- struct pam_response **resp,
- void *data)
+pam_chauthtok_conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
{
char input[PAM_MAX_MSG_SIZE];
int i;
struct pam_conv pam_conv = { pam_chauthtok_conv, NULL };
if (use_privsep)
- fatal("PAM: chauthtok not supprted with privsep");
+ fatal("Password expired (unable to change with privsep)");
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&pam_conv);
if (sshpam_err != PAM_SUCCESS)
void start_pam(const char *);
void finish_pam(void);
-int do_pam_account(const char *, const char *);
+u_int do_pam_account(void);
void do_pam_session(const char *, const char *);
void do_pam_setcred(int );
int is_pam_password_change_required(void);
authenticated = 0;
#endif
+#ifdef USE_PAM
+ if (options.use_pam && authenticated &&
+ !PRIVSEP(do_pam_account()))
+ authenticated = 0;
+#endif
+
/* Log before sending the reply */
auth_log(authctxt, authenticated, get_authname(type), info);
!auth_root_allowed(method))
authenticated = 0;
+#ifdef USE_PAM
+ if (options.use_pam && authenticated && !PRIVSEP(do_pam_account()))
+ authenticated = 0;
+#endif
+
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
#ifdef USE_PAM
int mm_answer_pam_start(int, Buffer *);
+int mm_answer_pam_account(int, Buffer *);
int mm_answer_pam_init_ctx(int, Buffer *);
int mm_answer_pam_query(int, Buffer *);
int mm_answer_pam_respond(int, Buffer *);
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
#ifdef USE_PAM
{MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+ {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
{MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
#endif
#ifdef USE_PAM
{MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+ {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
{MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
if (authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(auth_method))
authenticated = 0;
+#ifdef USE_PAM
+ /* PAM needs to perform account checks after auth */
+ if (options.use_pam) {
+ Buffer m;
+
+ buffer_init(&m);
+ mm_request_receive_expect(pmonitor->m_sendfd,
+ MONITOR_REQ_PAM_ACCOUNT, &m);
+ authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
+ buffer_free(&m);
+ }
+#endif
}
if (ent->flags & MON_AUTHDECIDE) {
xfree(user);
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
+
return (0);
}
+int
+mm_answer_pam_account(int socket, Buffer *m)
+{
+ u_int ret;
+
+ if (!options.use_pam)
+ fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
+ ret = do_pam_account();
+
+ buffer_put_int(m, ret);
+
+ mm_request_send(socket, MONITOR_ANS_PAM_ACCOUNT, m);
+
+ return (ret);
+}
+
static void *sshpam_ctxt, *sshpam_authok;
extern KbdintDevice sshpam_device;
MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
MONITOR_REQ_KRB5, MONITOR_ANS_KRB5,
MONITOR_REQ_PAM_START,
+ MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
MONITOR_REQ_PAM_QUERY, MONITOR_ANS_PAM_QUERY,
MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
buffer_free(&m);
}
+u_int
+mm_do_pam_account(void)
+{
+ Buffer m;
+ u_int ret;
+
+ debug3("%s entering", __func__);
+ if (!options.use_pam)
+ fatal("UsePAM=no, but ended up in %s anyway", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_PAM_ACCOUNT, &m);
+ ret = buffer_get_int(&m);
+
+ buffer_free(&m);
+
+ debug3("%s returning %d", __func__, ret);
+
+ return (ret);
+}
+
void *
mm_sshpam_init_ctx(Authctxt *authctxt)
{
#ifdef USE_PAM
void mm_start_pam(char *);
+u_int mm_do_pam_account(void);
void *mm_sshpam_init_ctx(struct Authctxt *);
int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_sshpam_respond(void *, u_int, char **);
if (options.use_pam && is_pam_password_change_required()) {
print_pam_messages();
do_pam_chauthtok();
+ /* XXX - signal [net] parent to enable forwardings */
}
#endif