blob: bbeb3f4e0aad19a9d9fa159ea990c5360e8a2318 [file] [log] [blame]
/*****************************************************************************\
* 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;
}