| /*****************************************************************************\ |
| * pam_slurm_adopt/helper.c |
| ***************************************************************************** |
| * Useful portions extracted from pam_slurm.c by Ryan Cox <ryan_cox@byu.edu> |
| * |
| * Copyright (C) 2002-2007 The Regents of the University of California. |
| * Copyright (C) 2008-2009 Lawrence Livermore National Security. |
| * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). |
| * UCRL-CODE-2002-040. |
| * |
| * Written by Chris Dunlap <cdunlap@llnl.gov> |
| * and Jim Garlick <garlick@llnl.gov> |
| * modified for Slurm by Moe Jette <jette@llnl.gov>. |
| * |
| * This file is part of pam_slurm, a PAM module for restricting access to |
| * the compute nodes within a cluster based on information obtained from |
| * Simple Linux Utility for Resource Management (Slurm). For details, see |
| * <http://www.llnl.gov/linux/slurm/>. |
| * |
| * pam_slurm 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. |
| * |
| * pam_slurm 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 pam_slurm; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| \*****************************************************************************/ |
| |
| #ifndef PAM_MODULE_NAME |
| # define PAM_MODULE_NAME "pam_slurm_adopt" |
| #endif |
| |
| #if HAVE_CONFIG_H |
| # include "config.h" |
| #endif |
| |
| #include <ctype.h> |
| #include <dlfcn.h> |
| #include <errno.h> |
| #include <pwd.h> |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <syslog.h> |
| #include <unistd.h> |
| |
| #include "slurm/slurm.h" |
| #include "src/common/slurm_xlator.h" |
| |
| #include "src/common/log.h" |
| |
| /* Define the externally visible functions in this file. |
| */ |
| #define PAM_SM_ACCOUNT |
| #include <security/pam_modules.h> |
| #include <security/_pam_macros.h> |
| |
| |
| /* Define the functions to be called before and after load since _init |
| * and _fini are obsolete, and their use can lead to unpredictable |
| * results. |
| */ |
| void __attribute__ ((constructor)) libpam_slurm_init(void); |
| void __attribute__ ((destructor)) libpam_slurm_fini(void); |
| |
| /* |
| * Handle for libslurm.so |
| * |
| * We open libslurm.so via dlopen () in order to pass the |
| * flag RTDL_GLOBAL so that subsequently loaded modules have |
| * access to libslurm symbols. This is pretty much only needed |
| * for dynamically loaded modules that would otherwise be |
| * linked against libslurm. |
| * |
| */ |
| static void * slurm_h = NULL; |
| |
| /* This function is necessary because libpam_slurm_init is called without access |
| * to the pam handle. |
| */ |
| static void |
| _log_msg(int level, const char *format, ...) |
| { |
| va_list args; |
| |
| openlog(PAM_MODULE_NAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV); |
| va_start(args, format); |
| vsyslog(level, format, args); |
| va_end(args); |
| closelog(); |
| return; |
| } |
| |
| /* |
| * pam 1.5.3 stopped providing _pam_drop_reply(). Our use does not currently |
| * fetch sensitive data so simply free this structure. |
| */ |
| static void _pam_slurm_drop_response(struct pam_response *reply, int replies) |
| { |
| for (int i = 0; i < replies; i++) { |
| if (reply[i].resp) |
| free(reply[i].resp); |
| } |
| free(reply); |
| } |
| |
| /* |
| * Sends a message to the application informing the user |
| * that access was denied due to Slurm. |
| */ |
| extern void |
| send_user_msg(pam_handle_t *pamh, const char *mesg) |
| { |
| int retval; |
| struct pam_conv *conv; |
| void *dummy; /* needed to eliminate warning: |
| * dereferencing type-punned pointer will |
| * break strict-aliasing rules */ |
| struct pam_message msg[1]; |
| const struct pam_message *pmsg[1]; |
| struct pam_response *prsp; |
| |
| info("send_user_msg: %s", mesg); |
| /* Get conversation function to talk with app. |
| */ |
| retval = pam_get_item(pamh, PAM_CONV, (const void **) &dummy); |
| conv = (struct pam_conv *) dummy; |
| if (retval != PAM_SUCCESS) { |
| _log_msg(LOG_ERR, "unable to get pam_conv: %s", |
| pam_strerror(pamh, retval)); |
| return; |
| } |
| |
| /* Construct msg to send to app. |
| */ |
| msg[0].msg_style = PAM_ERROR_MSG; |
| msg[0].msg = mesg; |
| pmsg[0] = &msg[0]; |
| prsp = NULL; |
| |
| /* Send msg to app and free the (meaningless) rsp. |
| */ |
| retval = conv->conv(1, pmsg, &prsp, conv->appdata_ptr); |
| if (retval != PAM_SUCCESS) |
| _log_msg(LOG_ERR, "unable to converse with app: %s", |
| pam_strerror(pamh, retval)); |
| if (prsp != NULL) |
| _pam_slurm_drop_response(prsp, 1); |
| |
| return; |
| } |
| |
| /* |
| * Dynamically open system's libslurm.so with RTLD_GLOBAL flag. |
| * This allows subsequently loaded modules access to libslurm symbols. |
| */ |
| extern void libpam_slurm_init (void) |
| { |
| char libslurmname[64]; |
| |
| if (slurm_h) |
| return; |
| |
| /* First try to use the same libslurm version ("libslurm.so.24.0.0"), |
| * Second try to match the major version number ("libslurm.so.24"), |
| * Otherwise use "libslurm.so" */ |
| if (snprintf(libslurmname, sizeof(libslurmname), |
| "libslurm.so.%d.%d.%d", SLURM_API_CURRENT, |
| SLURM_API_REVISION, SLURM_API_AGE) >= |
| (signed) sizeof(libslurmname) ) { |
| _log_msg (LOG_ERR, "Unable to write libslurmname\n"); |
| } else if ((slurm_h = dlopen(libslurmname, RTLD_NOW|RTLD_GLOBAL))) { |
| return; |
| } else { |
| _log_msg (LOG_INFO, "Unable to dlopen %s: %s\n", |
| libslurmname, dlerror ()); |
| } |
| |
| if (snprintf(libslurmname, sizeof(libslurmname), "libslurm.so.%d", |
| SLURM_API_CURRENT) >= (signed) sizeof(libslurmname) ) { |
| _log_msg (LOG_ERR, "Unable to write libslurmname\n"); |
| } else if ((slurm_h = dlopen(libslurmname, RTLD_NOW|RTLD_GLOBAL))) { |
| return; |
| } else { |
| _log_msg (LOG_INFO, "Unable to dlopen %s: %s\n", |
| libslurmname, dlerror ()); |
| } |
| |
| if (!(slurm_h = dlopen("libslurm.so", RTLD_NOW|RTLD_GLOBAL))) { |
| _log_msg (LOG_ERR, "Unable to dlopen libslurm.so: %s\n", |
| dlerror ()); |
| } |
| |
| return; |
| } |
| |
| extern void libpam_slurm_fini (void) |
| { |
| if (slurm_h) |
| dlclose (slurm_h); |
| return; |
| } |