diff options
author | Roger Leigh <rleigh@debian.org> | 2013-04-02 00:13:38 +0100 |
---|---|---|
committer | Roger Leigh <rleigh@debian.org> | 2013-04-02 22:22:23 +0100 |
commit | b3269de40c34c0623f1a3d649bee750e7f219533 (patch) | |
tree | 992ce57fbf795917b3f2c907c3bbcc4a1eb8981f /sbuild/sbuild-auth-pam.cc | |
parent | d5627e512f828bb459413e61c6c4bc2d452c1705 (diff) | |
download | schroot-b3269de40c34c0623f1a3d649bee750e7f219533.tar.gz |
sbuild: Remove sbuild- prefix
Diffstat (limited to 'sbuild/sbuild-auth-pam.cc')
-rw-r--r-- | sbuild/sbuild-auth-pam.cc | 461 |
1 files changed, 0 insertions, 461 deletions
diff --git a/sbuild/sbuild-auth-pam.cc b/sbuild/sbuild-auth-pam.cc deleted file mode 100644 index 130ece87..00000000 --- a/sbuild/sbuild-auth-pam.cc +++ /dev/null @@ -1,461 +0,0 @@ -/* Copyright © 2005-2013 Roger Leigh <rleigh@debian.org> - * - * schroot 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 3 of the License, or - * (at your option) any later version. - * - * schroot 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 program. If not, see - * <http://www.gnu.org/licenses/>. - * - *********************************************************************/ - -#include <config.h> - -#include "sbuild-auth-pam.h" -#include "sbuild-auth-pam-conv.h" -#include "sbuild-feature.h" - -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <sstream> - -#include <syslog.h> - -#include <boost/format.hpp> - -using std::cerr; -using std::endl; -using boost::format; -using namespace sbuild; - -#if defined(__LINUX_PAM__) -#define PAM_TEXT_DOMAIN "Linux-PAM" -#elif defined(__sun__) -#define PAM_TEXT_DOMAIN "SUNW_OST_SYSOSPAM" -#endif - -namespace -{ - - /* This is the glue to link PAM user interaction with auth_pam_conv. */ - int - auth_pam_conv_hook (int num_msg, - const struct pam_message **msgm, - struct pam_response **response, - void *appdata_ptr) - { - log_debug(DEBUG_NOTICE) << "PAM conversation hook started" << endl; - - try - { - if (appdata_ptr == 0) - return PAM_CONV_ERR; - - auth_pam_conv *conv = static_cast<auth_pam_conv *>(appdata_ptr); - assert (conv != 0); - - log_debug(DEBUG_INFO) << "Found PAM conversation handler" << endl; - - /* Construct a message vector */ - auth_pam_conv::message_list messages; - for (int i = 0; i < num_msg; ++i) - { - const struct pam_message *source = msgm[i]; - - auth_pam_message - message(static_cast<auth_pam_message::message_type>(source->msg_style), - source->msg); - - /* Replace PAM prompt */ - if (message.message == dgettext(PAM_TEXT_DOMAIN, "Password: ") || - message.message == dgettext(PAM_TEXT_DOMAIN, "Password:")) - { - std::string user = "unknown"; // Set in case auth is void - std::shared_ptr<auth_pam> auth = conv->get_auth(); - assert(auth && auth.get() != 0); // Check auth is not void - if (auth && auth.get() != 0) - user = auth->get_user(); - format fmt(_("[schroot] password for %1%: ")); - fmt % user; - message.message = fmt.str(); - } - - messages.push_back(message); - } - - log_debug(DEBUG_INFO) << "Set PAM conversation message vector" << endl; - - /* Do the conversation; an exception will be thrown on failure */ - conv->conversation(messages); - - log_debug(DEBUG_INFO) << "Run PAM conversation" << endl; - - /* Copy response into **reponse */ - struct pam_response *reply = - static_cast<struct pam_response *> - (malloc(sizeof(struct pam_response) * num_msg)); - - for (int i = 0; i < num_msg; ++i) - { - reply[i].resp_retcode = 0; - reply[i].resp = strdup(messages[i].response.c_str()); - } - - *response = reply; - reply = 0; - - log_debug(DEBUG_INFO) << "Set PAM conversation reply" << endl; - - return PAM_SUCCESS; - } - catch (std::exception const& e) - { - log_exception_error(e); - } - catch (...) - { - log_error() << _("An unknown exception occurred") << endl; - } - - return PAM_CONV_ERR; - } - - sbuild::feature feature_devlock("PAM", - N_("Pluggable Authentication Modules")); -} - -auth_pam::auth_pam (std::string const& service_name): - auth(service_name), - pam(0), - conv() -{ -} - -auth_pam::~auth_pam () -{ - // Shutdown PAM. - try - { - stop(); - } - catch (error const& e) - { - log_exception_error(e); - } -} - -auth::ptr -auth_pam::create (std::string const& service_name) -{ - return ptr(new auth_pam(service_name)); -} - -environment -auth_pam::get_auth_environment () const -{ - return environment(pam_getenvlist(this->pam)); -} - -auth_pam_conv::ptr& -auth_pam::get_conv () -{ - return this->conv; -} - -void -auth_pam::set_conv (auth_pam_conv::ptr& conv) -{ - this->conv = conv; -} - -void -auth_pam::start () -{ - assert(!this->user.empty()); - - if (this->pam != 0) - { - log_debug(DEBUG_CRITICAL) - << "pam_start FAIL (already initialised)" << endl; - throw error("Init PAM", PAM_DOUBLE_INIT); - } - - struct pam_conv conv_hook = - { - auth_pam_conv_hook, - reinterpret_cast<void *>(this->conv.get()) - }; - - int pam_status; - - if ((pam_status = - pam_start(this->service.c_str(), this->user.c_str(), - &conv_hook, &this->pam)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_start FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_start OK" << endl; -} - -void -auth_pam::stop () -{ - if (this->pam) // PAM must be initialised - { - int pam_status; - - if ((pam_status = - pam_end(this->pam, PAM_SUCCESS)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_end FAIL" << endl; - throw error(PAM_END); - } - - this->pam = 0; - log_debug(DEBUG_NOTICE) << "pam_end OK" << endl; - } -} - -void -auth_pam::authenticate (status auth_status) -{ - assert(!this->user.empty()); - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_set_item(this->pam, PAM_RUSER, this->ruser.c_str())) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_set_item (PAM_RUSER) FAIL" << endl; - throw error(_("Set RUSER"), PAM, pam_strerror(pam_status)); - } - - long hl = 256; /* sysconf(_SC_HOST_NAME_MAX); BROKEN with Debian libc6 2.3.2.ds1-22 */ - - char *hostname = new char[hl]; - try - { - if (gethostname(hostname, hl) != 0) - { - log_debug(DEBUG_CRITICAL) << "gethostname FAIL" << endl; - throw error(HOSTNAME, strerror(errno)); - } - - if ((pam_status = - pam_set_item(this->pam, PAM_RHOST, hostname)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_set_item (PAM_RHOST) FAIL" << endl; - throw error(_("Set RHOST"), PAM, pam_strerror(pam_status)); - } - } - catch (error const& e) - { - delete[] hostname; - hostname = 0; - throw; - } - delete[] hostname; - hostname = 0; - - const char *tty = ttyname(STDIN_FILENO); - if (tty) - { - if ((pam_status = - pam_set_item(this->pam, PAM_TTY, tty)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_set_item (PAM_TTY) FAIL" << endl; - throw error(_("Set TTY"), PAM, pam_strerror(pam_status)); - } - } - - /* Authenticate as required. */ - switch (auth_status) - { - case STATUS_NONE: - if ((pam_status = pam_set_item(this->pam, PAM_USER, this->user.c_str())) - != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_set_item (PAM_USER) FAIL" << endl; - throw error(_("Set USER"), PAM, pam_strerror(pam_status)); - } - break; - - case STATUS_USER: - if ((pam_status = pam_authenticate(this->pam, 0)) != PAM_SUCCESS) - { - log_debug(DEBUG_INFO) << "pam_authenticate FAIL" << endl; - syslog(LOG_AUTH|LOG_WARNING, "%s->%s Authentication failure", - this->ruser.c_str(), this->user.c_str()); - throw error(AUTHENTICATION, pam_strerror(pam_status)); - } - log_debug(DEBUG_NOTICE) << "pam_authenticate OK" << endl; - break; - - case STATUS_FAIL: - { - log_debug(DEBUG_INFO) << "PAM auth premature FAIL" << endl; - syslog(LOG_AUTH|LOG_WARNING, - "%s->%s Unauthorised", - this->ruser.c_str(), this->user.c_str()); - error e(AUTHORISATION); - // TRANSLATORS: %1% = program name (PAM service name) - std::string reason(_("You do not have permission to access the %1% service.")); - reason += '\n'; - reason += _("This failure will be reported."); - format fmt(reason); - fmt % this->service; - e.set_reason(fmt.str()); - throw e; - } - default: - break; - } -} - -void -auth_pam::setupenv () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - environment minimal(get_minimal_environment()); - - // Move into PAM environment. - for (const auto& env : minimal) - { - std::string env_string = env.first + "=" + env.second; - if ((pam_status = - pam_putenv(this->pam, env_string.c_str())) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_putenv FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - log_debug(DEBUG_INFO) - << format("pam_putenv: set %1%=%2%") % env.first % env.second - << endl; - } - - log_debug(DEBUG_NOTICE) << "pam_putenv OK" << endl; -} - -void -auth_pam::account () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_acct_mgmt(this->pam, 0)) != PAM_SUCCESS) - { - /* We don't handle changing expired passwords here, since we are - not login or ssh. */ - log_debug(DEBUG_WARNING) << "pam_acct_mgmt FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_acct_mgmt OK" << endl; -} - -void -auth_pam::cred_establish () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_setcred(this->pam, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_setcred FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_setcred OK" << endl; - - const char *authuser = 0; - const void *tmpcast = reinterpret_cast<const void *>(authuser); - pam_get_item(this->pam, PAM_USER, &tmpcast); - log_debug(DEBUG_INFO) - << format("PAM authentication succeeded for user %1%") % authuser - << endl; -} - -void -auth_pam::cred_delete () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_setcred(this->pam, PAM_DELETE_CRED)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_setcred (delete) FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_setcred (delete) OK" << endl; -} - -void -auth_pam::open_session () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_open_session(this->pam, 0)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_open_session FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_open_session OK" << endl; -} - -void -auth_pam::close_session () -{ - assert(this->pam != 0); // PAM must be initialised - - int pam_status; - - if ((pam_status = - pam_close_session(this->pam, 0)) != PAM_SUCCESS) - { - log_debug(DEBUG_WARNING) << "pam_close_session FAIL" << endl; - throw error(PAM, pam_strerror(pam_status)); - } - - log_debug(DEBUG_NOTICE) << "pam_close_session OK" << endl; -} - -bool -auth_pam::is_initialised () const -{ - return this->pam != 0; -} - -const char * -auth_pam::pam_strerror (int pam_error) -{ - assert(this->pam != 0); // PAM must be initialised - - return ::pam_strerror (this->pam, pam_error); -} |