aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb
diff options
context:
space:
mode:
Diffstat (limited to 'common/rfb')
-rw-r--r--common/rfb/CMakeLists.txt2
-rw-r--r--common/rfb/SSecurityPlain.cxx5
-rw-r--r--common/rfb/SSecurityPlain.h12
-rw-r--r--common/rfb/SSecurityRSAAES.cxx5
-rw-r--r--common/rfb/UnixPasswordValidator.cxx107
-rw-r--r--common/rfb/UnixPasswordValidator.h14
-rw-r--r--common/rfb/WinPasswdValidator.cxx3
-rw-r--r--common/rfb/WinPasswdValidator.h6
-rw-r--r--common/rfb/pam.c95
-rw-r--r--common/rfb/pam.h34
10 files changed, 136 insertions, 147 deletions
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
index e37142f8..23eb5e4f 100644
--- a/common/rfb/CMakeLists.txt
+++ b/common/rfb/CMakeLists.txt
@@ -76,7 +76,7 @@ if(WIN32)
endif(WIN32)
if(UNIX AND NOT APPLE)
- target_sources(rfb PRIVATE UnixPasswordValidator.cxx pam.c)
+ target_sources(rfb PRIVATE UnixPasswordValidator.cxx)
target_link_libraries(rfb ${PAM_LIBS})
endif()
diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx
index 06631f81..4fa63250 100644
--- a/common/rfb/SSecurityPlain.cxx
+++ b/common/rfb/SSecurityPlain.cxx
@@ -113,8 +113,9 @@ bool SSecurityPlain::processMsg()
password[plen] = 0;
username[ulen] = 0;
plen = 0;
- if (!valid->validate(sc, username, password))
- throw auth_error("Authentication failed");
+ std::string msg = "Authentication failed";
+ if (!valid->validate(sc, username, password, msg))
+ throw auth_error(msg);
}
return true;
diff --git a/common/rfb/SSecurityPlain.h b/common/rfb/SSecurityPlain.h
index f2bc3483..4c030455 100644
--- a/common/rfb/SSecurityPlain.h
+++ b/common/rfb/SSecurityPlain.h
@@ -29,14 +29,20 @@ namespace rfb {
class PasswordValidator {
public:
- bool validate(SConnection* sc, const char *username, const char *password)
- { return validUser(username) ? validateInternal(sc, username, password) : false; }
+ bool validate(SConnection* sc,
+ const char *username,
+ const char *password,
+ std::string &msg)
+ { return validUser(username) ? validateInternal(sc, username, password, msg) : false; }
static core::StringListParameter plainUsers;
virtual ~PasswordValidator() { }
protected:
- virtual bool validateInternal(SConnection* sc, const char *username, const char *password)=0;
+ virtual bool validateInternal(SConnection* sc,
+ const char *username,
+ const char *password,
+ std::string &msg) = 0;
static bool validUser(const char* username);
};
diff --git a/common/rfb/SSecurityRSAAES.cxx b/common/rfb/SSecurityRSAAES.cxx
index 6afb52dd..405005ab 100644
--- a/common/rfb/SSecurityRSAAES.cxx
+++ b/common/rfb/SSecurityRSAAES.cxx
@@ -583,9 +583,10 @@ void SSecurityRSAAES::verifyUserPass()
#elif !defined(__APPLE__)
UnixPasswordValidator *valid = new UnixPasswordValidator();
#endif
- if (!valid->validate(sc, username, password)) {
+ std::string msg = "Authentication failed";
+ if (!valid->validate(sc, username, password, msg)) {
delete valid;
- throw auth_error("Authentication failed");
+ throw auth_error(msg);
}
delete valid;
#else
diff --git a/common/rfb/UnixPasswordValidator.cxx b/common/rfb/UnixPasswordValidator.cxx
index 36b8dd7a..8239463a 100644
--- a/common/rfb/UnixPasswordValidator.cxx
+++ b/common/rfb/UnixPasswordValidator.cxx
@@ -22,24 +22,119 @@
#include <config.h>
#endif
+#include <assert.h>
+#include <string.h>
+#include <security/pam_appl.h>
+
#include <core/Configuration.h>
+#include <core/LogWriter.h>
#include <rfb/UnixPasswordValidator.h>
-#include <rfb/pam.h>
using namespace rfb;
+static core::LogWriter vlog("UnixPasswordValidator");
+
static core::StringParameter pamService
("PAMService", "Service name for PAM password validation", "vnc");
core::AliasParameter pam_service("pam_service", "Alias for PAMService",
&pamService);
-int do_pam_auth(const char *service, const char *username,
- const char *password);
+std::string UnixPasswordValidator::displayName;
+
+typedef struct
+{
+ const char *username;
+ const char *password;
+ std::string &msg;
+} AuthData;
+
+#if defined(__sun)
+static int pam_callback(int count, struct pam_message **in,
+ struct pam_response **out, void *ptr)
+#else
+static int pam_callback(int count, const struct pam_message **in,
+ struct pam_response **out, void *ptr)
+#endif
+{
+ int i;
+ AuthData *auth = (AuthData *) ptr;
+ struct pam_response *resp =
+ (struct pam_response *) malloc (sizeof (struct pam_response) * count);
+
+ if (!resp && count)
+ return PAM_CONV_ERR;
+
+ for (i = 0; i < count; i++) {
+ resp[i].resp_retcode = PAM_SUCCESS;
+ switch (in[i]->msg_style) {
+ case PAM_TEXT_INFO:
+ vlog.info("%s info: %s", (const char *) pamService, in[i]->msg);
+ auth->msg = in[i]->msg;
+ resp[i].resp = nullptr;
+ break;
+ case PAM_ERROR_MSG:
+ vlog.error("%s error: %s", (const char *) pamService, in[i]->msg);
+ auth->msg = in[i]->msg;
+ resp[i].resp = nullptr;
+ break;
+ case PAM_PROMPT_ECHO_ON: /* Send Username */
+ resp[i].resp = strdup(auth->username);
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* Send Password */
+ resp[i].resp = strdup(auth->password);
+ break;
+ default:
+ free(resp);
+ return PAM_CONV_ERR;
+ }
+ }
-bool UnixPasswordValidator::validateInternal(SConnection * /*sc*/,
+ *out = resp;
+ return PAM_SUCCESS;
+}
+
+bool UnixPasswordValidator::validateInternal(SConnection * /* sc */,
const char *username,
- const char *password)
+ const char *password,
+ std::string &msg)
{
- return do_pam_auth(pamService, username, password);
+ int ret;
+ AuthData auth = { username, password, msg };
+ struct pam_conv conv = {
+ pam_callback,
+ &auth
+ };
+ pam_handle_t *pamh = nullptr;
+ ret = pam_start(pamService, username, &conv, &pamh);
+ if (ret != PAM_SUCCESS) {
+ /* Can't call pam_strerror() here because the content of pamh undefined */
+ vlog.error("pam_start(%s) failed: %d", (const char *) pamService, ret);
+ return false;
+ }
+#ifdef PAM_XDISPLAY
+ /* At this point, displayName should never be empty */
+ assert(displayName.length() > 0);
+ /* Pass the display name to PAM modules but PAM_XDISPLAY may not be
+ * recognized by modules built with old versions of PAM */
+ ret = pam_set_item(pamh, PAM_XDISPLAY, displayName.c_str());
+ if (ret != PAM_SUCCESS && ret != PAM_BAD_ITEM) {
+ vlog.error("pam_set_item(PAM_XDISPLAY) failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+#endif
+ ret = pam_authenticate(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ vlog.error("pam_authenticate() failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+ ret = pam_acct_mgmt(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ vlog.error("pam_acct_mgmt() failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+ return true;
+error:
+ pam_end(pamh, ret);
+ return false;
}
diff --git a/common/rfb/UnixPasswordValidator.h b/common/rfb/UnixPasswordValidator.h
index 4d623d6c..a2cc89c5 100644
--- a/common/rfb/UnixPasswordValidator.h
+++ b/common/rfb/UnixPasswordValidator.h
@@ -26,9 +26,19 @@
namespace rfb
{
class UnixPasswordValidator: public PasswordValidator {
+ public:
+ static void setDisplayName(const std::string& display) {
+ displayName = display;
+ }
+
protected:
- bool validateInternal(SConnection * sc, const char *username,
- const char *password) override;
+ bool validateInternal(SConnection *sc,
+ const char *username,
+ const char *password,
+ std::string &msg) override;
+
+ private:
+ static std::string displayName;
};
}
diff --git a/common/rfb/WinPasswdValidator.cxx b/common/rfb/WinPasswdValidator.cxx
index 84832e81..a6281950 100644
--- a/common/rfb/WinPasswdValidator.cxx
+++ b/common/rfb/WinPasswdValidator.cxx
@@ -30,7 +30,8 @@ using namespace rfb;
// This method will only work for Windows NT, 2000, and XP (and possibly Vista)
bool WinPasswdValidator::validateInternal(rfb::SConnection* /*sc*/,
const char* username,
- const char* password)
+ const char* password,
+ std::string & /* msg */)
{
HANDLE handle;
diff --git a/common/rfb/WinPasswdValidator.h b/common/rfb/WinPasswdValidator.h
index 340a6234..993cafea 100644
--- a/common/rfb/WinPasswdValidator.h
+++ b/common/rfb/WinPasswdValidator.h
@@ -21,6 +21,7 @@
#ifndef __RFB_WINPASSWDVALIDATOR_H__
#define __RFB_WINPASSWDVALIDATOR_H__
+#include <string>
#include <rfb/SSecurityPlain.h>
namespace rfb
@@ -30,7 +31,10 @@ namespace rfb
WinPasswdValidator() {};
virtual ~WinPasswdValidator() {};
protected:
- bool validateInternal(SConnection *sc, const char* username, const char* password) override;
+ bool validateInternal(SConnection *sc,
+ const char *username,
+ const char *password,
+ std::string &msg) override;
};
}
diff --git a/common/rfb/pam.c b/common/rfb/pam.c
deleted file mode 100644
index f9e5ce74..00000000
--- a/common/rfb/pam.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2006 Martin Koegler
- * Copyright (C) 2010 TigerVNC Team
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <security/pam_appl.h>
-
-#include <rfb/pam.h>
-
-typedef struct
-{
- const char *username;
- const char *password;
-} AuthData;
-
-#if defined(__sun)
-static int pam_callback(int count, struct pam_message **in,
- struct pam_response **out, void *ptr)
-#else
-static int pam_callback(int count, const struct pam_message **in,
- struct pam_response **out, void *ptr)
-#endif
-{
- int i;
- AuthData *auth = (AuthData *) ptr;
- struct pam_response *resp =
- (struct pam_response *) malloc (sizeof (struct pam_response) * count);
-
- if (!resp && count)
- return PAM_CONV_ERR;
-
- for (i = 0; i < count; i++) {
- resp[i].resp_retcode = PAM_SUCCESS;
- switch (in[i]->msg_style) {
- case PAM_TEXT_INFO:
- case PAM_ERROR_MSG:
- resp[i].resp = 0;
- break;
- case PAM_PROMPT_ECHO_ON: /* Send Username */
- resp[i].resp = strdup(auth->username);
- break;
- case PAM_PROMPT_ECHO_OFF: /* Send Password */
- resp[i].resp = strdup(auth->password);
- break;
- default:
- free(resp);
- return PAM_CONV_ERR;
- }
- }
-
- *out = resp;
- return PAM_SUCCESS;
-}
-
-
-int do_pam_auth(const char *service, const char *username, const char *password)
-{
- int ret;
- AuthData auth = { username, password };
- struct pam_conv conv = {
- pam_callback,
- &auth
- };
- pam_handle_t *h = 0;
- ret = pam_start(service, username, &conv, &h);
- if (ret == PAM_SUCCESS)
- ret = pam_authenticate(h, 0);
- if (ret == PAM_SUCCESS)
- ret = pam_acct_mgmt(h, 0);
- pam_end(h, ret);
-
- return ret == PAM_SUCCESS ? 1 : 0;
-}
-
diff --git a/common/rfb/pam.h b/common/rfb/pam.h
deleted file mode 100644
index d378d19c..00000000
--- a/common/rfb/pam.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2006 Martin Koegler
- * Copyright (C) 2010 TigerVNC Team
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifndef __RFB_PAM_H__
-#define __RFB_PAM_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int do_pam_auth(const char *service, const char *username, const char *password);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif