#include <pam/pam_appl.h>
#endif
+/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
+#ifdef PAM_SUN_CODEBASE
+# define sshpam_const /* Solaris, HP-UX, AIX */
+#else
+# define sshpam_const const /* LinuxPAM, OpenPAM */
+#endif
+
#include "auth.h"
#include "auth-pam.h"
#include "buffer.h"
extern int compat20;
extern u_int utmp_len;
+/* so we don't silently change behaviour */
#ifdef USE_POSIX_THREADS
+# error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK"
+#endif
+
+/*
+ * Formerly known as USE_POSIX_THREADS, using this is completely unsupported
+ * and generally a bad idea. Use at own risk and do not expect support if
+ * this breaks.
+ */
+#ifdef UNSUPPORTED_POSIX_THREADS_HACK
#include <pthread.h>
/*
* Avoid namespace clash when *not* using pthreads for systems *with*
static void sshpam_free_ctx(void *);
static struct pam_ctxt *cleanup_ctxt;
-#ifndef USE_POSIX_THREADS
+#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/*
* Simulate threads with processes.
*/
static char **sshpam_env = NULL;
static Authctxt *sshpam_authctxt = NULL;
static const char *sshpam_password = NULL;
+static char badpw[] = "\b\n\r\177INCORRECT";
/* Some PAM implementations don't implement this */
#ifndef HAVE_PAM_GETENVLIST
debug3("PAM: %s entering", __func__);
-#ifndef USE_POSIX_THREADS
+#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Import variables set by do_pam_account */
sshpam_account_status = buffer_get_int(b);
sshpam_password_change_required(buffer_get_int(b));
* Conversation function for authentication thread.
*/
static int
-sshpam_thread_conv(int n, struct pam_message **msg,
+sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
Buffer buffer;
struct pam_conv sshpam_conv;
int flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
-#ifndef USE_POSIX_THREADS
+#ifndef UNSUPPORTED_POSIX_THREADS_HACK
extern char **environ;
char **env_from_pam;
u_int i;
const char *pam_user;
+ const char **ptr_pam_user = &pam_user;
- pam_get_item(sshpam_handle, PAM_USER, (void **)&pam_user);
+ pam_get_item(sshpam_handle, PAM_USER,
+ (sshpam_const void **)ptr_pam_user);
environ[0] = NULL;
if (sshpam_authctxt != NULL) {
buffer_put_cstring(&buffer, "OK");
-#ifndef USE_POSIX_THREADS
+#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Export variables set by do_pam_account */
buffer_put_int(&buffer, sshpam_account_status);
buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
buffer_put_int(&buffer, i);
for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
buffer_put_cstring(&buffer, env_from_pam[i]);
-#endif /* USE_POSIX_THREADS */
+#endif /* UNSUPPORTED_POSIX_THREADS_HACK */
/* XXX - can't do much about an error here */
ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
}
static int
-sshpam_null_conv(int n, struct pam_message **msg,
+sshpam_null_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
debug3("PAM: %s entering, %d messages", __func__, n);
static struct pam_conv null_conv = { sshpam_null_conv, NULL };
static int
-sshpam_store_conv(int n, struct pam_message **msg,
+sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
{
extern char *__progname;
const char *pam_rhost, *pam_user, *user = authctxt->user;
+ const char **ptr_pam_user = &pam_user;
if (sshpam_handle != NULL) {
/* We already have a PAM context; check if the user matches */
sshpam_err = pam_get_item(sshpam_handle,
- PAM_USER, (void **)&pam_user);
+ PAM_USER, (sshpam_const void **)ptr_pam_user);
if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
return (0);
pam_end(sshpam_handle, sshpam_err);
**prompts = NULL;
}
if (type == PAM_SUCCESS) {
+ if (!sshpam_authctxt->valid ||
+ (sshpam_authctxt->pw->pw_uid == 0 &&
+ options.permit_root_login != PERMIT_YES))
+ fatal("Internal error: PAM auth "
+ "succeeded when it should have "
+ "failed");
import_environments(&buffer);
*num = 0;
**echo_on = 0;
return (-1);
}
buffer_init(&buffer);
- buffer_put_cstring(&buffer, *resp);
+ if (sshpam_authctxt->valid &&
+ (sshpam_authctxt->pw->pw_uid != 0 ||
+ options.permit_root_login == PERMIT_YES))
+ buffer_put_cstring(&buffer, *resp);
+ else
+ buffer_put_cstring(&buffer, badpw);
if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
buffer_free(&buffer);
return (-1);
}
static int
-sshpam_tty_conv(int n, struct pam_message **msg,
+sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
char input[PAM_MAX_MSG_SIZE];
* display.
*/
static int
-sshpam_passwd_conv(int n, struct pam_message **msg,
+sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
{
int flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
- static char badpw[] = "\b\n\r\177INCORRECT";
if (!options.use_pam || sshpam_handle == NULL)
fatal("PAM: %s called when PAM disabled or failed to "