diff --git a/configure.ac b/configure.ac index df29cb58a9e0196de16f8803450b3f22d60b1630..fe85a201a918cc1d337dc1f6fd54849784417d0c 100644 --- a/configure.ac +++ b/configure.ac @@ -80,7 +80,7 @@ dnl Checks for header files. dnl AC_CHECK_HEADERS(popt.h mcheck.h values.h socket.h sys/socket.h \ stdbool.h sys/ipc.h sys/shm.h sys/sem.h errno.h \ - stdlib.h \ + stdlib.h dirent.h \ ) AC_HEADER_SYS_WAIT AC_HEADER_TIME @@ -484,6 +484,8 @@ AC_CONFIG_FILES([Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile + src/plugins/Makefile + src/plugins/auth/Makefile doc/Makefile doc/man/Makefile testsuite/Makefile diff --git a/etc/slurm.conf.example b/etc/slurm.conf.example index 63854f470a5ab8a7897edf4ee49008560b7c94b9..84b467f9dff293c7935a55ad609b0a1af62f4538 100644 --- a/etc/slurm.conf.example +++ b/etc/slurm.conf.example @@ -127,6 +127,21 @@ # SlurmctldPidFile=/var/slurm/slurmctld.pid # default: "/var/run/slurmctld.pid" # SlurmdPidFile=/var/slurm/slurmctld.pid # default: "/var/run/slurmd.pid" +# +# o Define the authentication method for communicating between SLURM +# components +# +# "auth/none" : no authentication, the default +# "auth/authd" : Brett Chun's authd +# +# AuthType=auth/none + +# +# o Define the places to look for SLURM plugins. This is a +# colon-separated list of directories, just like the PATH +# environment variable. +# +# PluginDir=/usr/local/lib # default # # o Define some timeout values for the slurm controller and backup diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in index d5b54b84509cfc8f56e2d728516b0212bbd51d0b..fc88900e702af22e5a02bf1295d28ebe80f3bd37 100644 --- a/slurm/slurm.h.in +++ b/slurm/slurm.h.in @@ -388,6 +388,8 @@ typedef struct slurm_ctl_conf { char *slurm_conf; /* pathname of slurm config file */ char *state_save_location;/* pathname of slurmctld state save * directory */ + char *plugindir; /* pathname to plugins */ + char *authtype; /* authentication type */ char *tmp_fs; /* pathname of temporary file system */ char *job_credential_private_key; /* path to private key */ char *job_credential_public_certificate;/* path to public certificate*/ diff --git a/src/Makefile.am b/src/Makefile.am index 7076d4a12fb4596da541cc1d5be6c20c87c44442..0bd080ce9bac76ce0f97801cc21df45a5024a49a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,9 @@ # $Id$ if USE_INCLUDED_POPT -SUBDIRS = popt common api slurmctld slurmd srun scontrol scancel squeue sinfo +SUBDIRS = popt common api slurmctld slurmd srun scontrol scancel squeue sinfo plugins else -SUBDIRS = common api slurmctld slurmd srun scontrol scancel squeue sinfo +SUBDIRS = common api slurmctld slurmd srun scontrol scancel squeue sinfo plugins endif # make sure popt gets distributed: diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 1b5427a2a813fc1e8eaeef04877f0e8fb3f57416..cf87fcbe9ae4297ffc95ef084f4d2ace4b66d36f 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -11,12 +11,6 @@ else elan_sources = endif -if WITH_AUTHD -auth_sources = slurm_auth_authd.c -else -auth_sources = slurm_auth_authd.c -endif - noinst_LTLIBRARIES = \ libcommon.la \ libdaemonize.la \ @@ -40,10 +34,11 @@ libcommon_la_SOURCES = \ pack.c pack.h \ parse_spec.c parse_spec.h \ plugin.c plugin.h \ + plugrack.c plugrack.h \ read_config.c read_config.h \ slurm_errno.c \ slurm_protocol_api.c \ - slurm_protocol_api.h \ + slurm_protocol_api.h \ slurm_protocol_pack.c \ slurm_protocol_pack.h \ slurm_protocol_util.c \ @@ -55,10 +50,9 @@ libcommon_la_SOURCES = \ slurm_protocol_defs.c \ slurm_protocol_defs.h \ util-net.c util-net.h \ - slurm_auth.h \ + slurm_auth.c slurm_auth.h \ macros.h \ - $(elan_sources) \ - $(auth_sources) + $(elan_sources) libdaemonize_la_SOURCES = \ daemonize.c \ @@ -80,6 +74,6 @@ libeio_la_SOURCES = \ EXTRA_libcommon_la_SOURCES = \ qsw.c qsw.h -libcommon_la_LIBADD = $(AUTHD_LIBS) $(SSL_LIBS) +libcommon_la_LIBADD = $(SSL_LIBS) libcred_la_LIBADD = $(SSL_LIBS) libcred_la_LDFLAGS = $(SSL_LDFLAGS) diff --git a/src/common/plugin.c b/src/common/plugin.c index c0f49efcf023f422cb56d06369d3452fae3b0da5..5f959d1ece7c9a197d134be4d771c4798dd8557e 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -24,10 +24,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. \*****************************************************************************/ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include <sys/types.h> #include <stdio.h> -#include <assert.h> -#include <dlfcn.h> +#include <dlfcn.h> /* don't know if there's an autoconf for this. */ #include "src/common/plugin.h" @@ -38,52 +41,69 @@ plugin_load_from_file( const char *fq_path ) plugin_handle_t plug; /* Try to open the shared object. */ - plug = dlopen( fq_path, RTLD_LAZY ); + plug = dlopen( fq_path, RTLD_NOW ); if ( plug == NULL ) { - return NULL; + return PLUGIN_INVALID_HANDLE; } /* Now see if our required symbols are defined. */ if ( ( dlsym( plug, PLUGIN_NAME ) == NULL ) || ( dlsym( plug, PLUGIN_TYPE ) == NULL ) || ( dlsym( plug, PLUGIN_VERSION ) == NULL ) ) { - return NULL; + return PLUGIN_INVALID_HANDLE; } return plug; } +/* + * Must test plugin validity before doing dlopen() and dlsym() + * operations because some implementations of these functions + * crash if the library handle is not valid. + */ + void plugin_unload( plugin_handle_t plug ) { - assert( plug ); - (void) dlclose( plug ); + if ( plug != PLUGIN_INVALID_HANDLE ) (void) dlclose( plug ); } void * plugin_get_sym( plugin_handle_t plug, const char *name ) { - return dlsym( plug, name ); + if ( plug != PLUGIN_INVALID_HANDLE ) + return dlsym( plug, name ); + else + return NULL; } const char * plugin_get_name( plugin_handle_t plug ) { - return (const char *) dlsym( plug, PLUGIN_NAME ); + if ( plug != PLUGIN_INVALID_HANDLE ) + return (const char *) dlsym( plug, PLUGIN_NAME ); + else + return NULL; } const char * plugin_get_type( plugin_handle_t plug ) { - return (const char *) dlsym( plug, PLUGIN_TYPE ); + if ( plug != PLUGIN_INVALID_HANDLE ) + return (const char *) dlsym( plug, PLUGIN_TYPE ); + else + return NULL; } uint32_t plugin_get_version( plugin_handle_t plug ) { - uint32_t *ptr = (uint32_t *) dlsym( plug, PLUGIN_VERSION ); + uint32_t *ptr; + + if ( plug == PLUGIN_INVALID_HANDLE ) return 0; + ptr = (uint32_t *) dlsym( plug, PLUGIN_VERSION ); return ptr ? *ptr : 0; } diff --git a/src/common/plugrack.c b/src/common/plugrack.c new file mode 100644 index 0000000000000000000000000000000000000000..d8461db382f33dad48a15827c8f917533a4428dc --- /dev/null +++ b/src/common/plugrack.c @@ -0,0 +1,588 @@ +/*****************************************************************************\ + * plugrack.c - an intelligent container for plugins + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by AUTHOR <AUTHOR@llnl.gov>. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * 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. + * + * 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 SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#if HAVE_CONFIG_H +# include "config.h" + +# if HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +# else /* ! HAVE_DIRENT_H */ +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# endif /* HAVE_DIRENT_H */ + +# if STDC_HEADERS +# include <string.h> +# include <stdlib.h> +# else /* ! STDC_HEADERS */ +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex + char *strchr(), *strrchr(); +# endif /* HAVE_STRCHR */ +# endif /* STDC_HEADERS */ + +# if HAVE_UNISTD_H +# include <unistd.h> +# endif /* HAVE_UNISTD_H */ +# if HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif +# if HAVE_SYS_STAT_H +# include <sys/stat.h> +# endif + +#else /* ! HAVE_CONFIG_H */ +# include <dirent.h> +# include <string.h> +# include <stdlib.h> +# include <unistd.h> +# include <dirent.h> +# include <sys/types.h> +# include <sys/stat.h> +#endif /* HAVE_CONFIG_H */ + +#include "src/common/xassert.h" +#include "src/common/xmalloc.h" +#include "src/common/xstring.h" +#include "src/common/plugrack.h" + +/* + * Represents a plugin in the rack. + * + * full_type is the fully-qualified plugin type, e.g., "auth/kerberos". + * For the low-level plugin interface the type can be whatever it needs + * to be. For the rack-level interface, the type exported by the plugin + * must be of the form "<major>/<minor>". + * + * fq_path is the fully-qualified pathname to the plugin. + * + * plug is the plugin handle. If it is equal to PLUGIN_INVALID_HANDLE + * then the plugin is not currently loaded in memory. + * + * refcount shows how many clients have requested to use the plugin. + * If this is zero, the rack code may decide to unload the plugin. + */ +typedef struct _plugrack_entry { + const char *full_type; + const char *fq_path; + plugin_handle_t plug; + int refcount; +} plugrack_entry_t; + +/* + * Implementation of the plugin rack. + * + * entries is the list of plugrack_entry_t. + * + * uid is the Linux UID of the person authorized to own the plugin + * and write to the plugin file and the directory where it is stored. + * This field is used only if paranoia is nonzero. + * + * paranoia is a set of bit flags indicating what operations should be + * done to verify the integrity and authority of the plugin before + * loading it. + */ +struct _plugrack { + List entries; + const char *major_type; + uid_t uid; + uint8_t paranoia; +}; + +#define PLUGRACK_UID_NOBODY 99 /* RedHat's, anyway. */ + +/* + * Destructor function for the List code. This should entirely + * clean up a plugin_entry_t. + */ +static void +plugrack_entry_destructor( void *v ) +{ + plugrack_entry_t *victim = v; + + if ( victim == NULL ) return; + + /* + * Free memory and unload the plugin if necessary. The assert + * is to make sure we were actually called from the List destructor + * which should only be callable from plugrack_destroy(). + */ + xassert( victim->refcount == 0 ); + if ( victim->full_type ) xfree( victim->full_type ); + if ( victim->fq_path ) xfree( victim->fq_path ); + if ( victim->plug != PLUGIN_INVALID_HANDLE ) plugin_unload( victim->plug ); + xfree( victim ); +} + +/* + * Check a pathname to see if it is owned and writable by the appropriate + * users, and writable by no one else. The path can be either to a file + * or to a directory. This is so, when fishing for plugins in a whole + * directory, we can test the directory once and then each file. + * + * Returns non-zero if the file system node indicated by the path name + * is owned by the user in the plugin rack and not writable by anyone + * else, and these actions are requested by the rack's paranoia policy. + */ +static int +accept_path_paranoia( plugrack_t rack, + const char *fq_path, + int check_own, + int check_write ) +{ + struct stat st; + + /* Internal function, so assert rather than fail gracefully. */ + xassert( rack ); + xassert( fq_path ); + + if ( stat( fq_path, &st ) < 0 ) { + return 0; + } + + /* Is path owned by authorized user? */ + if ( check_own ) { + if ( st.st_uid != rack->uid ) return 0; + } + + /* Is path writable by others? */ + if ( check_write ) { + if ( ( st.st_mode & S_IWGRP ) || ( st.st_mode & S_IWOTH ) ) return 0; + } + + return 1; +} + + +/* + * Check a file to see if its permissions and location are appropriate + * for a plugin. This checks both a file and its parent directory for + * correct ownership and writability. + * + * The permissions and ownerships to check are given in the paranoia + * policy of the plugin rack. + * + * Returns nonzero if the plugin is acceptable. + */ +static int +accept_paranoia( plugrack_t rack, const char *fq_path ) +{ + char *local; + char *p; + + xassert( rack ); + xassert( fq_path ); + + /* Trivial accept. */ + if ( ! rack->paranoia ) return 1; + + /* Make a local copy of the path name so we can write into it. */ + local = alloca( strlen( fq_path ) + 1 ); + strcpy( local, fq_path ); + + if ( ! accept_path_paranoia( rack, + local, + rack->paranoia & PLUGRACK_PARANOIA_FILE_OWN, + rack->paranoia & PLUGRACK_PARANOIA_FILE_WRITABLE ) ) { + return 0; + } + + /* + * Find the directory name by chopping off the last path element. + * This also helps weed out malformed file names. We specify that + * plugins be specified by fully-qualified pathnames and that means + * it should have at least one delimiter. + */ + if ( ( p = strrchr( local, '/' ) ) == NULL ) { + return 0; + } + if ( p != local ) *p = 0; + + return accept_path_paranoia( rack, + local, + rack->paranoia & PLUGRACK_PARANOIA_DIR_OWN, + rack->paranoia & PLUGRACK_PARANOIA_DIR_WRITABLE ); +} + +/* + * Load a plugin. Check its type, but not any of the onwership or + * writability. It is presumed that those have already been checked. + */ +static plugin_handle_t +plugrack_open_plugin( plugrack_t rack, const char *fq_path ) +{ + plugin_handle_t plug; + + if ( ! rack ) return PLUGIN_INVALID_HANDLE; + if ( ! fq_path ) return PLUGIN_INVALID_HANDLE; + + /* See if we can actually load the plugin. */ + plug = plugin_load_from_file( fq_path ); + if ( plug == PLUGIN_INVALID_HANDLE ) return PLUGIN_INVALID_HANDLE; + + /* Now see if this is the right type. */ + if ( rack->major_type && + ( strncmp( rack->major_type, + plugin_get_type( plug ), + strlen( rack->major_type ) ) != 0 ) ) { + plugin_unload( plug ); + return PLUGIN_INVALID_HANDLE; + } + + return plug; +} + + +plugrack_t plugrack_create( void ) +{ + plugrack_t rack = (plugrack_t) xmalloc( sizeof( struct _plugrack ) ); + + rack->paranoia = PLUGRACK_PARANOIA_NONE; + rack->major_type = NULL; + rack->uid = PLUGRACK_UID_NOBODY; + rack->entries = list_create( plugrack_entry_destructor ); + if ( rack->entries == NULL ) { + xfree( rack ); + return NULL; + } + return rack; +} + + +int +plugrack_destroy( plugrack_t rack ) +{ + ListIterator it; + plugrack_entry_t *e; + + if ( ! rack ) return SLURM_ERROR; + + /* + * See if there are any plugins still being used. If we unload them, + * the program might crash because cached virtual mapped addresses + * will suddenly be outside our virtual address space. + */ + it = list_iterator_create( rack->entries ); + while ( ( e = list_next( it ) ) != NULL ) { + if ( e->refcount > 0 ) { + list_iterator_destroy( it ); + return SLURM_ERROR; /* plugins still in use. */ + } + } + list_iterator_destroy( it ); + + list_destroy( rack->entries ); + xfree( rack ); + return SLURM_SUCCESS; +} + + +int +plugrack_set_major_type( plugrack_t rack, const char *type ) +{ + if ( ! rack ) return SLURM_ERROR; + if ( ! type ) return SLURM_ERROR; + + /* Free any pre-existing type. */ + if ( rack->major_type ) xfree( rack->major_type ); + rack->major_type = NULL; + + /* Install a new one. */ + if ( type != NULL ) { + rack->major_type = xstrdup( type ); + if ( rack->major_type == NULL ) return SLURM_ERROR; + } + + return SLURM_SUCCESS; +} + + +int +plugrack_set_paranoia( plugrack_t rack, + const uint32_t flags, + const uid_t uid ) + +{ + if ( ! rack ) return SLURM_ERROR; + + rack->paranoia = flags; + if ( flags ) { + rack->uid = uid; + } + + return SLURM_SUCCESS; +} + +int +plugrack_add_opened_plugin( plugrack_t rack, + plugin_handle_t *plug, + const char *fq_path ) +{ + plugrack_entry_t *e; + + if ( ! rack ) return SLURM_ERROR; + if ( ! plug ) return SLURM_ERROR; + if ( ! fq_path ) return SLURM_ERROR; + + e = (plugrack_entry_t *) xmalloc( sizeof( plugrack_entry_t ) ); + + e->full_type = xstrdup( plugin_get_type( plug ) ); + e->fq_path = xstrdup( fq_path ); + e->plug = plug; + e->refcount = 0; + + list_append( rack->entries, e ); + + return SLURM_SUCCESS; +} + + +int +plugrack_add_plugin_file( plugrack_t rack, const char *fq_path ) +{ + plugin_handle_t plug; + + if ( ! rack ) return SLURM_ERROR; + if ( ! fq_path ) return SLURM_ERROR; + + /* + * See if we should open this plugin. Paranoia checks must + * always be done first since code can be executed in the plugin + * simply by opening it. + */ + if ( ! accept_paranoia( rack, fq_path ) ) return SLURM_ERROR; + + /* Try to open plugin, testing the type. */ + plug = plugrack_open_plugin( rack, fq_path ); + if ( plug == PLUGIN_INVALID_HANDLE ) return SLURM_ERROR; + + /* Add it to the list. */ + return plugrack_add_opened_plugin( rack, plug, fq_path ); +} + + + +int +plugrack_read_dir( plugrack_t rack, + const char *dir ) +{ + char *fq_path; + char *tail; + DIR *dirp; + struct dirent *e; + struct stat st; + plugin_handle_t plug; + + if ( ! rack ) return SLURM_ERROR; + if ( ! dir ) return SLURM_ERROR; + + /* Allocate a buffer for fully-qualified path names. */ + fq_path = alloca( strlen( dir ) + NAME_MAX + 1 ); + xassert( fq_path ); + + /* + * Write the directory name in it, then a separator, then + * keep track of where we want to write the individual file + * names. + */ + strcpy( fq_path, dir ); + tail = &fq_path[ strlen( dir ) ]; + *tail = '/'; + ++tail; + + /* Check whether we should be paranoid about this directory. */ + if ( ! accept_path_paranoia( rack, + dir, + rack->paranoia & PLUGRACK_PARANOIA_DIR_OWN, + rack->paranoia & PLUGRACK_PARANOIA_DIR_WRITABLE ) ) { + return SLURM_ERROR; + } + + /* Open the directory. */ + dirp = opendir( dir ); + if ( dirp == NULL ) return SLURM_ERROR; + + while ( 1 ) { + e = readdir( dirp ); + if ( e == NULL ) break; + + /* + * Compose file name. Where NAME_MAX is defined it represents the + * largest file name given in a dirent. This macro is used in the + * allocation of "tail" above, so this unbounded copy should work. + */ + strcpy( tail, e->d_name ); + + /* Check only regular files. */ + if ( stat( fq_path, &st ) < 0 ) continue; + if ( ! S_ISREG( st.st_mode ) ) continue; + + /* See if we should be paranoid about this file. */ + if ( ! accept_path_paranoia( rack, + dir, + rack->paranoia & PLUGRACK_PARANOIA_FILE_OWN, + rack->paranoia & PLUGRACK_PARANOIA_FILE_WRITABLE ) ) { + continue; + } + + /* Load the plugin. */ + plug = plugrack_open_plugin( rack, fq_path ); + if ( plug == PLUGIN_INVALID_HANDLE ) { + continue; + } + + /* Add it to the list. */ + (void) plugrack_add_opened_plugin( rack, plug, fq_path ); + } + + return SLURM_SUCCESS; +} + +int +plugrack_read_cache( plugrack_t rack, + const char *cache_file ) +{ + /* Don't care for now. */ + + return SLURM_ERROR; +} + + +int +plugrack_purge_idle( plugrack_t rack ) +{ + ListIterator it; + plugrack_entry_t *e; + + if ( ! rack ) return SLURM_ERROR; + + it = list_iterator_create( rack->entries ); + while ( ( e = list_next( it ) ) != NULL ) { + if ( ( e->plug != PLUGIN_INVALID_HANDLE ) && + ( e->refcount == 0 ) ){ + plugin_unload( e->plug ); + e->plug = PLUGIN_INVALID_HANDLE; + } + } + + list_iterator_destroy( it ); + return SLURM_SUCCESS; +} + + +int +plugrack_load_all( plugrack_t rack ) +{ + ListIterator it; + plugrack_entry_t *e; + + if ( ! rack ) return SLURM_ERROR; + + it = list_iterator_create( rack->entries ); + while ( ( e = list_next( it ) ) != NULL ) { + if ( e->plug == PLUGIN_INVALID_HANDLE ) { + (void) plugin_load_from_file( e->fq_path ); + } + } + + list_iterator_destroy( it ); + return SLURM_SUCCESS; +} + + +int +plugrack_write_cache( plugrack_t rack, + const char *cache ) +{ + /* Not implemented. */ + + return SLURM_SUCCESS; +} + +plugin_handle_t +plugrack_use_by_type( plugrack_t rack, + const char *full_type ) +{ + ListIterator it; + plugrack_entry_t *e; + + if ( ! rack ) return PLUGIN_INVALID_HANDLE; + if ( ! full_type ) return PLUGIN_INVALID_HANDLE; + + it = list_iterator_create( rack->entries ); + while ( ( e = list_next( it ) ) != NULL ) { + if ( strcmp( full_type, e->full_type ) != 0 ) continue; + + /* See if plugin is loaded. */ + if ( e->plug == PLUGIN_INVALID_HANDLE ) { + e->plug = plugin_load_from_file( e->fq_path ); + } + + /* If load was successful, increment the reference count. */ + if ( e->plug == PLUGIN_INVALID_HANDLE ) + e->refcount++; + + /* + * Return the plugin, even if it failed to load -- this serves + * as an error return value. + */ + list_iterator_destroy( it ); + return e->plug; + } + + /* Couldn't find a suitable plugin. */ + list_iterator_destroy( it ); + return PLUGIN_INVALID_HANDLE; +} + + +int +plugrack_finished_with_plugin( plugrack_t rack, plugin_handle_t plug ) +{ + ListIterator it; + plugrack_entry_t *e; + + if ( ! rack ) return SLURM_ERROR; + + it = list_iterator_create( rack->entries ); + while ( ( e = list_next( it ) ) != NULL ) { + if ( e->plug == plug ) { + e->refcount--; + if ( e->refcount < 0 ) e->refcount = 0; + + /* Do something here with purge policy. */ + + list_iterator_destroy( it ); + return SLURM_SUCCESS; + } + } + + /* Plugin not in this rack. */ + list_iterator_destroy( it ); + return SLURM_ERROR; +} diff --git a/src/common/plugrack.h b/src/common/plugrack.h new file mode 100644 index 0000000000000000000000000000000000000000..121444dea06ebdfaa26d6d503faa018899283c75 --- /dev/null +++ b/src/common/plugrack.h @@ -0,0 +1,186 @@ +/*****************************************************************************\ + * plugrack.h - an intelligent container for plugins + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by AUTHOR <AUTHOR@llnl.gov>. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * 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. + * + * 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 SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#ifndef __PLUGRACK_H__ +#define __PLUGRACK_H__ + +#include "src/common/plugin.h" +#include "src/common/list.h" + +/* Opaque type for plugin rack. */ +typedef struct _plugrack * plugrack_t; + +/* + * Returns a new plugin rack object on success and NULL on failure. + */ +plugrack_t plugrack_create( void ); + +/* + * Destroy a plugin rack. All the associated plugins are unloaded and + * all associated memory is deallocated. + * + * Returns a SLURM errno. + */ +int plugrack_destroy( plugrack_t rack ); + +/* + * Set the major type of the plugins for this rack. This affects + * subsequent calls to add plugins from files. + * + * Pass NULL to disable typing in plugins handled by this rack. + * This is the default. + * + * Returns a SLURM errno. + */ +int plugrack_set_major_type( plugrack_t rack, const char *type ); + +/* + * Paranoia settings. OR these together, if desired. + * + * _DIR_OWN - verify that the directory containing the plugin is owned + * by a certain user. + * _DIR_WRITABLE - verify that the directory containing the plugin is + * not writable by anyone except its owner. + * _FILE_OWN - verify that the plugin is owned by a certain user. + * _FILE_WRITABLE - verify that the plugin is not writable by anyone + * except its onwer. + */ +#define PLUGRACK_PARANOIA_NONE 0x00 +#define PLUGRACK_PARANOIA_DIR_OWN 0x01 +#define PLUGRACK_PARANOIA_DIR_WRITABLE 0x02 +#define PLUGRACK_PARANOIA_FILE_OWN 0x04 +#define PLUGRACK_PARANOIA_FILE_WRITABLE 0x08 + +/* + * Indicate the manner in which the rack should be paranoid about + * accepting plugins. + * + * paranoia_flags is an ORed combination of the flags listed above. + * They do not combine across separate calls; the flags must be fully + * specified at each call. + * + * The paranoia setting affects only subsequent attempts to place + * plugins in the rack. + * + * If the flag parameter specifies ownership checking, "uid" gives the + * numerical user ID of the authorized owner of the plugin and the + * directory where it resides. If no ownership checking is requested, + * this parameter is ignored. + * + * Returns a SLURM errno. + */ +int plugrack_set_paranoia( plugrack_t rack, + const uint32_t paranoia_flags, + const uid_t uid ); + +/* + * Add a plugin to a rack by giving the pathname to the plugin. + * + * If a type has been set for this rack, the plugin's major type must + * match or an error results. + * + * Returns a SLURM errno. + */ +int plugrack_add_plugin_file( plugrack_t rack, const char *fq_path ); + +/* + * Add plugins to a rack by scanning the given directory. If a + * type has been set for this rack, only those plugins whose major type + * matches the rack's type will be loaded. + * + * Returns a SLURM errno. + */ +int plugrack_read_dir( plugrack_t rack, + const char *dir ); + +/* + * Identical to plugrack_read_dir() except that additional criteria are + * tested: + * + * 1. The directory must be owned by the specified UID and must be + * writable by that user only; "other" and "group" may not write to + * it. + * + * 2. Each candidate plugin must be owned by the specified UID and + * must not be writable by any other means. In addition, the plugin's + * setuid bit must be cleared. + */ +int plugrack_read_dir_paranoid( plugrack_t rack, + const char *dir, + uid_t uid ); + +/* + * Add plugins to the rack by reading the given cache. Note that plugins + * may not actually load, but the rack will be made aware of them. + * + * NOT CURRENTLY IMPLEMENTED. + */ +int plugrack_read_cache( plugrack_t rack, + const char *cache ); + +/* + * Remove from memory all plugins that are not currently in use by the + * program. + * + * Returns a SLURM errno. + */ +int plugrack_unload_idle( plugrack_t rack ); + +/* + * Load into memory all plugins which are currently unloaded. + * + * Returns a SLURM errno. + */ +int plugrack_load_all( plugrack_t rack ); + +/* + * Write the current contents of the plugin rack to a file + * in cache format, suitable to be read later using plugrack_read_cache(). + * + * Returns a SLURM errno. + */ +int plugrack_write_cache( plugrack_t rack, const char *cache ); + +/* + * Find a plugin in the rack which matches the given minor type, + * load it if necessary, and return a handle to it. + * + * Returns PLUGIN_INVALID_HANDLE if a suitable plugin cannot be + * found or loaded. + */ +plugin_handle_t plugrack_use_by_type( plugrack_t rack, + const char *type ); + +/* + * Indicate that a plugin is no longer needed. Whether the plugin + * is actually unloaded depends on the rack's disposal policy. + * + * Returns a SLURM errno. + */ +int plugrack_finished_with_plugin( plugrack_t rack, plugin_handle_t plug ); + + +#endif /*__PLUGRACK_H__*/ diff --git a/src/common/read_config.c b/src/common/read_config.c index fb5e884475e4e5055471dfa4333090a8b99f0bc8..1e6251936853c2cbf8242e87b4e3452634698ce1 100644 --- a/src/common/read_config.c +++ b/src/common/read_config.c @@ -128,6 +128,8 @@ init_slurm_conf (slurm_ctl_conf_t *ctl_conf_ptr) xfree (ctl_conf_ptr->slurmd_spooldir); ctl_conf_ptr->slurmd_timeout = (uint16_t) NO_VAL; xfree (ctl_conf_ptr->state_save_location); + xfree (ctl_conf_ptr->plugindir); + xfree (ctl_conf_ptr->authtype ); xfree (ctl_conf_ptr->tmp_fs); return; } @@ -163,6 +165,7 @@ parse_config_spec (char *in_line, slurm_ctl_conf_t *ctl_conf_ptr) char *slurmctld_logfile = NULL, *slurmctld_port = NULL; char *slurmd_logfile = NULL, *slurmd_port = NULL; char *slurmd_spooldir = NULL, *slurmd_pidfile = NULL; + char *plugindir = NULL, *authtype = NULL; char *job_credential_private_key = NULL; char *job_credential_public_certificate = NULL; long first_job_id = -1; @@ -198,7 +201,9 @@ parse_config_spec (char *in_line, slurm_ctl_conf_t *ctl_conf_ptr) "SlurmdPort=", 's', &slurmd_port, "SlurmdSpoolDir=", 's', &slurmd_spooldir, "SlurmdTimeout=", 'd', &slurmd_timeout, - "StateSaveLocation=", 's', &state_save_location, + "StateSaveLocation=", 's', &state_save_location, + "PluginDir=", 's', &plugindir, + "AuthType=", 's', &authtype, "TmpFS=", 's', &tmp_fs, "END"); @@ -417,6 +422,22 @@ parse_config_spec (char *in_line, slurm_ctl_conf_t *ctl_conf_ptr) ctl_conf_ptr->state_save_location = state_save_location; } + if ( plugindir ) { + if ( ctl_conf_ptr->plugindir ) { + error( MULTIPLE_VALUE_MSG, "PluginDir" ); + xfree( ctl_conf_ptr->plugindir ); + } + ctl_conf_ptr->plugindir = plugindir; + } + + if ( authtype ) { + if ( ctl_conf_ptr->authtype ) { + error( MULTIPLE_VALUE_MSG, "AuthType" ); + xfree( ctl_conf_ptr->authtype ); + } + ctl_conf_ptr->authtype = authtype; + } + if ( tmp_fs ) { if ( ctl_conf_ptr->tmp_fs ) { error (MULTIPLE_VALUE_MSG, "TmpFS"); diff --git a/src/common/slurm_auth.c b/src/common/slurm_auth.c new file mode 100644 index 0000000000000000000000000000000000000000..f7b7e864edce8b7720f36abb7013a944b1077842 --- /dev/null +++ b/src/common/slurm_auth.c @@ -0,0 +1,476 @@ +/*****************************************************************************\ + * slurm_auth.h - implementation-independent authentication API definitions + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Kevin Tew <tew1@llnl.gov> et. al. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * 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. + * + * 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 SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#include <stdlib.h> +#include <string.h> + +#include <pthread.h> + +#include "src/common/macros.h" +#include "src/common/xmalloc.h" +#include "src/common/xassert.h" +#include "src/common/xstring.h" +#include "src/common/read_config.h" +#include "src/common/slurm_auth.h" +#include "src/common/plugin.h" +#include "src/common/plugrack.h" + +/* + * WARNING: Do not change the order of these fields or add additional + * fields at the beginning of the structure. If you do, authentication + * plugins will stop working. If you need to add fields, add them at the + * end of the structure. + */ +typedef struct slurm_auth_ops { + void * (*alloc) ( void ); + void (*free) ( void *cred ); + int (*activate) ( void *cred, int secs ); + int (*verify) ( void *cred ); + uid_t (*get_uid) ( void *cred ); + gid_t (*get_gid) ( void *cred ); + void (*pack) ( void *cred, Buf buf ); + int (*unpack) ( void *cred, Buf buf ); + void (*print) ( void *cred, FILE *fp ); +} slurm_auth_ops_t; + +/* + * Implementation of the authentication context. Hopefully everything + * having to do with plugins will be abstracted under here so that the + * callers can just deal with creating a context and asking for the + * operations implemented pertinent to that context. + * + * auth_type - the string (presumably from configuration files) + * describing the desired form of authentication, such as "auth/munged" + * or "auth/kerberos" or "auth/none". + * + * plugin_list - the plugin rack managing the loading and unloading of + * plugins for authencation. + * + * cur_plugin - the plugin currently supplying operations to the caller. + * + * ops - a table of pointers to functions in the plugin which correspond + * to the standardized plugin API. We create this table by text references + * into the plugin's symbol table. + */ +struct slurm_auth_context { + char *auth_type; + plugrack_t plugin_list; + plugin_handle_t cur_plugin; + slurm_auth_ops_t ops; +}; + +/* + * A global authentication context. "Global" in the sense that there's + * only one, with static bindings. We don't export it. + */ +static slurm_auth_context_t g_context = NULL; + +static slurm_ctl_conf_t conf; +static pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER; + +static char * +get_plugin_dir( void ) +{ + slurm_mutex_lock( &config_lock ); + if ( conf.slurmd_port == 0 ) { + read_slurm_conf_ctl( &conf ); + } + if ( conf.plugindir == NULL ) { + conf.plugindir = xstrdup( "/usr/local/lib" ); + } + slurm_mutex_unlock( &config_lock ); + + return conf.plugindir; +} + +static char * +get_auth_type( void ) +{ + slurm_mutex_lock( &config_lock ); + if ( conf.slurmd_port == 0 ) { + read_slurm_conf_ctl( &conf ); + } + if ( conf.authtype == NULL ) { + conf.authtype = xstrdup( "auth/none" ); + } + slurm_mutex_unlock( &config_lock ); + + return conf.authtype; +} + + +/* + * Resolve the operations from the plugin. + */ +static slurm_auth_ops_t * +slurm_auth_get_ops( slurm_auth_context_t c ) +{ + /* + * These strings must be kept in the same order as the fields + * declared for slurm_auth_ops_t. + */ + static const char *syms[] = { + "slurm_auth_alloc", + "slurm_auth_free", + "slurm_auth_activate", + "slurm_auth_verify", + "slurm_auth_get_uid", + "slurm_auth_get_gid", + "slurm_auth_pack", + "slurm_auth_unpack", + "slurm_auth_print" + }; + int n_syms = sizeof( syms ) / sizeof( char * ); + + /* Get the plugin list, if needed. */ + if ( c->plugin_list == NULL ) { + c->plugin_list = plugrack_create(); + if ( c->plugin_list == NULL ) { + verbose( "Unable to create a plugin manager" ); + return NULL; + } + + plugrack_set_major_type( c->plugin_list, "auth" ); + plugrack_set_paranoia( c->plugin_list, PLUGRACK_PARANOIA_NONE, 0 ); + plugrack_read_dir( c->plugin_list, get_plugin_dir() ); + } + + /* Find the correct plugin. */ + c->cur_plugin = plugrack_use_by_type( c->plugin_list, c->auth_type ); + if ( c->cur_plugin == PLUGIN_INVALID_HANDLE ) { + verbose( "can't find a plugin for type %s", c->auth_type ); + return NULL; + } + + /* Dereference the API. */ + if ( plugin_get_syms( c->cur_plugin, + n_syms, + syms, + (void **) &c->ops ) < n_syms ) { + verbose( "incomplete plugin detected" ); + return NULL; + } + + return &c->ops; +} + + +slurm_auth_context_t +slurm_auth_context_create( const char *auth_type ) +{ + slurm_auth_context_t c; + + if ( auth_type == NULL ) { + debug( "slurm_auth_context_create: no authentication type" ); + return NULL; + } + + c = (slurm_auth_context_t) xmalloc( sizeof( struct slurm_auth_context ) ); + + /* Copy the authentication type. */ + c->auth_type = strdup( auth_type ); + if ( c->auth_type == NULL ) { + debug( "can't make local copy of authentication type" ); + xfree( c ); + return NULL; + } + + /* Plugin rack is demand-loaded on first reference. */ + c->plugin_list = NULL; + + c->cur_plugin = PLUGIN_INVALID_HANDLE; + + return c; +} + +int +slurm_auth_context_destroy( slurm_auth_context_t c ) +{ + /* + * Must check return code here because plugins might still + * be loaded and active. + */ + if ( c->plugin_list ) { + if ( plugrack_destroy( c->plugin_list ) != SLURM_SUCCESS ) { + return SLURM_ERROR; + } + } + + free( c->auth_type ); + xfree( c ); + + return SLURM_SUCCESS; +} + +int +slurm_auth_init( void ) +{ + if ( g_context ) { + return SLURM_SUCCESS; + } + + + g_context = slurm_auth_context_create( get_auth_type() ); + if ( g_context == NULL ) { + verbose( "cannot create a context for %s", get_auth_type() ); + return SLURM_ERROR; + } + + if ( slurm_auth_get_ops( g_context ) == NULL ) { + verbose( "cannot resolve plugin operations" ); + return SLURM_ERROR; + } else { + return SLURM_SUCCESS; + } +} + +/* + * Static bindings for an arbitrary authentication context. Heaven + * help you if you try to pass credentials from one context to the + * functions for a different context. + */ +void * +c_slurm_auth_alloc( slurm_auth_context_t c ) +{ + if ( c == NULL ) return NULL; + if ( c->ops.alloc ) { + return (*(c->ops.alloc))(); + } else { + return NULL; + } +} + +void +c_slurm_auth_free( slurm_auth_context_t c, void *cred ) +{ + if ( ( c == NULL ) || ( cred == NULL ) ) return; + if ( c->ops.free ) { + (*(c->ops.free))( cred ); + } +} + +int +c_slurm_auth_activate( slurm_auth_context_t c, void *cred, int secs ) +{ + if ( ( c == NULL ) || ( cred == NULL ) ) return SLURM_ERROR; + if ( c->ops.activate ) { + return (*(c->ops.activate))( cred, secs ); + } else { + return SLURM_ERROR; + } +} + +int +c_slurm_auth_verify( slurm_auth_context_t c, void *cred ) +{ + if ( ( c == NULL ) || ( cred == NULL ) ) return SLURM_ERROR; + if ( c->ops.verify ) { + return (*(c->ops.verify))( cred ); + } else { + return SLURM_ERROR; + } +} + +uid_t +c_slurm_auth_get_uid( slurm_auth_context_t c, void *cred ) +{ + if ( ( c == NULL ) || ( cred == NULL ) ) return SLURM_AUTH_NOBODY; + if ( c->ops.verify ) { + return (*(c->ops.get_uid))( cred ); + } else { + return SLURM_AUTH_NOBODY; + } +} + +gid_t +c_slurm_auth_get_gid( slurm_auth_context_t c, void *cred ) +{ + if ( ( c == NULL ) || ( cred == NULL ) ) return SLURM_AUTH_NOBODY; + if ( c->ops.verify ) { + return (*(c->ops.get_gid))( cred ); + } else { + return SLURM_AUTH_NOBODY; + } +} + + +void +c_slurm_auth_pack( slurm_auth_context_t c, void *cred, Buf buf ) +{ + if ( ( c == NULL ) || ( cred == NULL ) || ( buf == NULL ) ) + return; + if ( c->ops.pack ) { + (*(c->ops.pack))( cred, buf ); + } +} + + +int +c_slurm_auth_unpack( slurm_auth_context_t c, void *cred, Buf buf ) +{ + if ( ( c == NULL ) || ( cred == NULL ) || ( buf == NULL ) ) + return SLURM_ERROR; + if ( c->ops.unpack ) { + return (*(c->ops.unpack))( cred, buf ); + } else { + return SLURM_ERROR; + } +} + +void +c_slurm_auth_print( slurm_auth_context_t c, void *cred, FILE *fp ) +{ + if ( ( c == NULL ) || ( cred == NULL ) || ( fp == NULL ) ) + return; + if ( c->ops.print ) { + (*(c->ops.print))( cred, fp ); + } +} + + +/* + * Static bindings for the global authentication context. The test + * of the function pointers is omitted here because the global + * context initialization includes a test for the completeness of + * the API function dispatcher. + */ + +void * +g_slurm_auth_alloc( void ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't allocate credential - authentication init failed" ); + return NULL; + } + } + + return (*(g_context->ops.alloc))(); +} + +void +g_slurm_auth_free( void *cred ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't free credential - authentication init failed" ); + return; + } + } + + (*(g_context->ops.free))( cred ); +} + +int +g_slurm_auth_activate( void *cred, int secs ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't activate credential - authentication init failed" ); + return SLURM_ERROR; + } + } + + return (*(g_context->ops.activate))( cred, secs ); +} + +int +g_slurm_auth_verify( void *cred ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't verify credential - authentication init failed" ); + return SLURM_ERROR; + } + } + + return (*(g_context->ops.verify))( cred ); +} + +uid_t +g_slurm_auth_get_uid( void *cred ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't get UID - authentication init failed" ); + return SLURM_AUTH_NOBODY; + } + } + + return (*(g_context->ops.get_uid))( cred ); +} + +gid_t +g_slurm_auth_get_gid( void *cred ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't get GID - authentication init failed" ); + return SLURM_AUTH_NOBODY; + } + } + + return (*(g_context->ops.get_gid))( cred ); +} + +void +g_slurm_auth_pack( void *cred, Buf buf ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't pack credential - authentication init failed" ); + return; + } + } + + (*(g_context->ops.pack))( cred, buf ); +} + +int +g_slurm_auth_unpack( void *cred, Buf buf ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't unpack credential - authentication init failed" ); + return SLURM_ERROR; + } + } + + return (*(g_context->ops.unpack))( cred, buf ); +} + +void +g_slurm_auth_print( void *cred, FILE *fp ) +{ + if ( ! g_context ) { + if ( slurm_auth_init() != SLURM_SUCCESS ) { + error( "can't print credential - authentication init failed" ); + return; + } + } + + (*(g_context->ops.print))( cred, fp ); +} diff --git a/src/common/slurm_auth.h b/src/common/slurm_auth.h index 370037d1b20fe46833e829e507d399cd9660ad9e..57104a413da96da573bb46679c0ef653c11fdbad 100644 --- a/src/common/slurm_auth.h +++ b/src/common/slurm_auth.h @@ -27,6 +27,8 @@ #ifndef __SLURM_AUTHENTICATION_H__ #define __SLURM_AUTHENTICATION_H__ +#include <stdio.h> + #if HAVE_CONFIG_H # include "config.h" # if HAVE_INTTYPES_H @@ -40,58 +42,97 @@ # include <inttypes.h> #endif /* HAVE_CONFIG_H */ +#include "src/common/plugrack.h" #include "src/common/pack.h" - -/* slurm_auth_credentials_t is an opaque type whose definition is to - * be completed in the implementation specific module +/* + * This is really two APIs. We provide an authentication context object + * which can be bound to any authentication type available in the system + * and several of which may happily exist together. The API thunks with + * a "c_" prefix operate on these. The typical order of calls is: + * + * slurm_auth_context_t foo = slurm_auth_context_create( my type ); + * void *bar = c_slurm_auth_alloc( foo ); + * c_slurm_auth_activate( foo, bar, 1 ); + * c_slurm_auth_verify( foo, bar ); + * c_slurm_auth_free( foo, bar ); + * slurm_auth_context_destroy( foo ); + * + * There is also a parallel API operating on a global authentication + * context, one per application. The API thunks with the "g_" prefix + * operate on that global instance. It is initialized implicitly if + * necessary when any API thunk is called, or explicitly with + * + * slurm_auth_init(); + * + * The authentication type and other parameters are taken from the + * system's global configuration. A typical order of calls is: + * + * void *bar = g_slurm_auth_alloc(); + * g_slurm_auth_activate( bar, 1 ); + * g_slurm_auth_verify( bar ); + * g_slurm_auth_free( bar ); + * */ -typedef struct slurm_auth_credentials * slurm_auth_t; /* - * Allocation a new set of credentials from the free store. Returns - * NULL if no allocation is possible. + * SLURM authentication context opaque type. */ -slurm_auth_t slurm_auth_alloc_credentials( void ); +typedef struct slurm_auth_context * slurm_auth_context_t; /* - * Deallocate credentials allocated with slurm_auth_alloc_credentials(). + * Create an authentication context. + * + * Returns NULL on failure. */ -void slurm_auth_free_credentials( slurm_auth_t cred ); +slurm_auth_context_t slurm_auth_context_create( const char *auth_type ); /* - * Populate the credentials and validate them for use. - * cred - The credential to activate. - * seconds_to_live - the number of seconds after validation that - * the credential expires - * Returns SLURM_ERROR if the credentials could not be populated, - * validated, or if the authentication daemon is not running. + * Destroy an authentication context. Any jumptables returned by + * calls to slurm_auth_get_ops() for this context will silently become + * invalid, and calls to their functions may result in core dumps and + * other nasty behavior. + * + * Returns a SLURM errno. */ -int slurm_auth_activate_credentials( slurm_auth_t cred, - time_t seconds_to_live ); +int slurm_auth_context_destroy( slurm_auth_context_t ctxt ); /* - * Verify the credentials. Returns SLURM_ERROR if the credentials are - * invalid or has expired. + * This is what the UID and GID accessors return on error. The value + * is currently RedHat Linux's ID for the user "nobody". */ -int slurm_auth_verify_credentials( slurm_auth_t cred ); +#define SLURM_AUTH_NOBODY 99 /* - * Extract user and group identification from the credentials. - * They are trustworthy only if the credentials have first been - * verified. + * Static bindings for an arbitrary authentication context. We avoid + * exposing the API directly to avoid object lifetime issues. */ -uid_t slurm_auth_uid( slurm_auth_t cred ); -gid_t slurm_auth_gid( slurm_auth_t cred ); +void *c_slurm_auth_alloc( slurm_auth_context_t c ); +void c_slurm_auth_free( slurm_auth_context_t c, void *cred ); +int c_slurm_auth_activate( slurm_auth_context_t c, void *cred, int secs ); +int c_slurm_auth_verify( slurm_auth_context_t c, void *cred ); +uid_t c_slurm_auth_get_uid( slurm_auth_context_t c, void *cred ); +gid_t c_slurm_auth_get_gid( slurm_auth_context_t c, void *cred ); +void c_slurm_auth_pack( slurm_auth_context_t c, void *cred, Buf buf ); +int c_slurm_auth_unpack( slurm_auth_context_t c, void *cred, Buf buf ); +void c_slurm_auth_print( slurm_auth_context_t c, void *cred, FILE *fp ); /* - * Methods for packing and unpacking the credentials for transport. + * Prepare the global context. */ -void slurm_auth_pack_credentials( slurm_auth_t cred, Buf buffer ); -int slurm_auth_unpack_credentials( slurm_auth_t *cred, Buf buffer ); +int slurm_auth_init( void ); -#if DEBUG -void slurm_auth_print_credentials( slurm_auth_t *cred ); -#endif +/* + * Static bindings for the global authentication context. + */ +void *g_slurm_auth_alloc( void ); +void g_slurm_auth_free( void *cred ); +int g_slurm_auth_activate( void *cred, int secs ); +int g_slurm_auth_verify( void *cred ); +uid_t g_slurm_auth_get_uid( void *cred ); +gid_t g_slurm_auth_get_gid( void *cred ); +void g_slurm_auth_pack( void *cred, Buf buf ); +int g_slurm_auth_unpack( void *cred, Buf buf ); +void g_slurm_auth_print( void *cred, FILE *fp ); #endif /*__SLURM_AUTHENTICATION_H__*/ diff --git a/src/common/slurm_auth_authd.c b/src/common/slurm_auth_authd.c deleted file mode 100644 index 84df98d372e58f5d74325eefbd73f6528cd1554e..0000000000000000000000000000000000000000 --- a/src/common/slurm_auth_authd.c +++ /dev/null @@ -1,243 +0,0 @@ -/*****************************************************************************\ - * slurm_auth_authd.c - authentication module for Brent Chun's authd - ***************************************************************************** - * Copyright (C) 2002 The Regents of the University of California. - * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). - * Written by Keven Tew <tew1@llnl.gov>. - * UCRL-CODE-2002-040. - * - * This file is part of SLURM, a resource management program. - * For details, see <http://www.llnl.gov/linux/slurm/>. - * - * 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. - * - * 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 SLURM; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -\*****************************************************************************/ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <pwd.h> -#include <grp.h> - -#if HAVE_SSL -# include <openssl/rsa.h> -# include <openssl/pem.h> -# include <openssl/err.h> -#endif - -/* - * Because authd's authentication scheme relies on determining the - * owner of a Unix domain socket over which the request is made to - * authenticate credentials, we must do our own socket thing unless - * the transport abstraction layer will provide for Unix domain - * sockets. - */ -#include <sys/socket.h> -#include <sys/un.h> - -#include <slurm/slurm_errno.h> - -#include "src/common/log.h" -#include "src/common/pack.h" -#include "src/common/slurm_auth.h" -#include "src/common/xmalloc.h" - -#define UNIX_PATH_MAX 108 /* Cribbed from /usr/include/linux/un.h */ - -#if HAVE_AUTHD -# include <auth.h> -/* Completion of slurm_auth_credentials_t from slurm_auth.h - */ -typedef struct slurm_auth_credentials { - credentials creds; /* Authd's credential structure. */ - signature sig; /* RSA hash for the credentials. */ -} slurm_auth_credentials_t; -#else /* !HAVE_AUTHD */ -/* XXX: This needs to go away. This module should only be compiled in if - * we have authd. - */ -#include <sys/types.h> -#include <time.h> - -typedef struct authd_credentials { - uid_t uid; - gid_t gid; - time_t valid_from; - time_t valid_to; -} credentials; - -typedef struct authd_signature { - unsigned char data[1]; -} signature; - -typedef struct slurm_auth_credentials { - credentials creds; - signature sig; -} slurm_auth_credentials_t; -#endif - -static int slurm_sign_auth_credentials( slurm_auth_credentials_t *cred ); - -slurm_auth_t -slurm_auth_alloc_credentials( void ) -{ - return (slurm_auth_t) xmalloc(sizeof(struct slurm_auth_credentials)); -} - - -void -slurm_auth_free_credentials( slurm_auth_t cred ) -{ - xfree( cred ); -} - - -int -slurm_auth_activate_credentials( slurm_auth_t cred, time_t ttl ) -{ - int rc; - /* Initialize credentials with our user and group IDs. */ - cred->creds.uid = geteuid(); - cred->creds.gid = getegid(); - - /* Set the valid time interval. */ - cred->creds.valid_from = time( NULL ); - cred->creds.valid_to = cred->creds.valid_from + ttl; - - /* Sign the credentials. */ - if ((rc = slurm_sign_auth_credentials(cred)) < 0) - return rc; - - return SLURM_SUCCESS; -} - - -int -slurm_auth_verify_credentials( slurm_auth_t cred ) -{ -#ifdef HAVE_AUTHD - int rc = auth_verify_signature(&cred->creds, &cred->sig); - if (rc < 0) { - switch (rc) { - case AUTH_FOPEN_ERROR: - slurm_seterrno_ret(ESLURM_AUTH_FOPEN_ERROR); - case AUTH_RSA_ERROR: - case AUTH_CRED_ERROR: - slurm_seterrno_ret(ESLURM_AUTH_CRED_INVALID); - case AUTH_NET_ERROR: - slurm_seterrno_ret(ESLURM_AUTH_NET_ERROR); - default: - slurm_seterrno_ret(ESLURM_AUTH_CRED_INVALID); - } - } -#endif - return SLURM_SUCCESS; -} - - -/* Should really do this with inline accessors. */ -uid_t slurm_auth_uid( slurm_auth_t cred ) -{ - return cred->creds.uid; -} - -gid_t slurm_auth_gid( slurm_auth_t cred ) -{ - return cred->creds.gid; -} - -void slurm_auth_pack_credentials( slurm_auth_t cred, Buf buffer) -{ - uint16_t chunk_size = sizeof( signature ); - - pack32 ( cred->creds.uid, buffer ); - pack32 ( cred->creds.gid, buffer ); - pack_time( cred->creds.valid_from, buffer ); - pack_time( cred->creds.valid_to, buffer ); - packmem ( cred->sig.data, chunk_size, buffer ); -} - - -int slurm_auth_unpack_credentials( slurm_auth_t *credp, Buf buffer) -{ - uint16_t dummy; - char *data; - slurm_auth_t cred; - - cred = slurm_auth_alloc_credentials(); - safe_unpack32 ( &cred->creds.uid, buffer ); - safe_unpack32 ( &cred->creds.gid, buffer ); - safe_unpack_time ( &cred->creds.valid_from, buffer ); - safe_unpack_time ( &cred->creds.valid_to, buffer ); - safe_unpackmem_ptr( &data, &dummy, buffer ); - memcpy( cred->sig.data, data, sizeof( signature ) ); - *credp = cred; - return SLURM_SUCCESS; - - unpack_error: - slurm_auth_free_credentials( cred ); - *credp = NULL; - return SLURM_ERROR; -} - - -static int -slurm_sign_auth_credentials( slurm_auth_t cred ) -{ -#ifdef HAVE_AUTHD - assert(cred != NULL); - return auth_get_signature(&cred->creds, &cred->sig); -#else - return SLURM_SUCCESS; -#endif -} - -#if DEBUG -void -slurm_auth_print_credentials( slurm_auth_credentials_t *cred ) -{ - struct passwd *pwent; - struct group *grent; - int i; - - printf( "-- BEGIN CLIENT CREDENTIALS\n" ); - pwent = getpwuid( cred->creds.uid ); - printf( " user : %d (%s)\n", - cred->creds.uid, - pwent ? pwent->pw_name : "unknown" ); - grent = getgrgid( cred->creds.gid ); - printf( " group : %d (%s)\n", - cred->creds.gid, - grent ? grent->gr_name : "unknown" ); - - printf( " effective : %ld %s", - cred->creds.valid_from, - ctime( &cred->creds.valid_from ) ); - printf( " expires : %ld %s", - cred->creds.valid_to, - ctime( &cred->creds.valid_to ) ); - printf( " signature :" ); - for ( i = 0; i < sizeof( cred->sig.data ); ++i ) { - if ( ( i % 16 ) == 0 ) printf( "\n " ); - if ( ( i % 4 ) == 0 ) putchar( ' ' ); - printf( "%02x", cred->sig.data[ i ] ); - } - printf( "\n-- END CLIENT CREDENTIALS\n" ); -} -#endif /*DEBUG*/ diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c index b714ac5c25a4830588ed257e6c091a01c1bf2dc3..3a0b78bfa79dbeae57644378d491315545411599 100644 --- a/src/common/slurm_protocol_api.c +++ b/src/common/slurm_protocol_api.c @@ -257,6 +257,7 @@ slurm_fd slurm_open_controller_conn() debug ("Open connection to secondary controller failed: %m"); } + return connection_fd; } @@ -332,7 +333,7 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) char *buftemp; header_t header; int rc; - slurm_auth_t creds; + void *auth_cred; Buf buffer; buftemp = xmalloc(SLURM_PROTOCOL_MAX_MESSAGE_BUFFER_SIZE); @@ -343,6 +344,9 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) xfree(buftemp); return rc; } + + auth_cred = g_slurm_auth_alloc(); + #if _DEBUG _print_data (buftemp,rc); #endif @@ -355,15 +359,15 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) slurm_seterrno_ret(SLURM_PROTOCOL_VERSION_ERROR); } - /* unpack cred */ - if (slurm_auth_unpack_credentials(&creds, buffer)) { + /* unpack authentication cred */ + if (g_slurm_auth_unpack( auth_cred, buffer)) { free_buf(buffer); slurm_seterrno_ret(ESLURM_PROTOCOL_INCOMPLETE_PACKET); } /* verify credentials */ - if ((rc = slurm_auth_verify_credentials(creds)) != SLURM_SUCCESS) { - slurm_auth_free_credentials(creds); + if ((rc = g_slurm_auth_verify(auth_cred)) != SLURM_SUCCESS) { + g_slurm_auth_free(auth_cred); free_buf(buffer); slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR); } @@ -372,14 +376,12 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) msg->msg_type = header.msg_type; if ((header.body_length > remaining_buf(buffer)) || (unpack_msg(msg, buffer) != SLURM_SUCCESS)) { - slurm_auth_free_credentials(creds); + g_slurm_auth_free(auth_cred); free_buf(buffer); slurm_seterrno_ret(ESLURM_PROTOCOL_INCOMPLETE_PACKET); } - msg->cred = (void *) creds; - msg->cred_type = header.cred_type; - msg->cred_size = header.cred_length; + msg->cred = (void *) auth_cred; free_buf(buffer); return SLURM_SUCCESS; @@ -424,19 +426,16 @@ int slurm_send_node_msg(slurm_fd open_fd, slurm_msg_t * msg) { header_t header; int rc; - unsigned int cred_len, msg_len, tmp_len; + unsigned int msg_len, tmp_len; Buf buffer; - slurm_auth_t creds = slurm_auth_alloc_credentials(); - - if (creds == NULL) - error("unable to alloc credentials"); + void *auth_cred; /* initialize header */ + auth_cred = g_slurm_auth_alloc(); init_header(&header, msg->msg_type, SLURM_PROTOCOL_NO_FLAGS); - rc = slurm_auth_activate_credentials(creds, CREDENTIAL_TTL_SEC); + rc = g_slurm_auth_activate(auth_cred, CREDENTIAL_TTL_SEC); if (rc != SLURM_SUCCESS) /* Try once more */ - rc = slurm_auth_activate_credentials(creds, - CREDENTIAL_TTL_SEC); + rc = g_slurm_auth_activate(auth_cred, CREDENTIAL_TTL_SEC); if (rc != SLURM_SUCCESS) { error ("slurm_send_node_msg: sending msg with unsigned credential, rc=%d)", @@ -448,10 +447,8 @@ int slurm_send_node_msg(slurm_fd open_fd, slurm_msg_t * msg) pack_header(&header, buffer); /* pack creds */ - tmp_len = get_buf_offset(buffer); - slurm_auth_pack_credentials(creds, buffer); - slurm_auth_free_credentials(creds); - cred_len = get_buf_offset(buffer) - tmp_len; + g_slurm_auth_pack(auth_cred, buffer); + g_slurm_auth_free(auth_cred); /* pack msg */ tmp_len = get_buf_offset(buffer); @@ -459,7 +456,8 @@ int slurm_send_node_msg(slurm_fd open_fd, slurm_msg_t * msg) msg_len = get_buf_offset(buffer) - tmp_len; /* update header with correct cred and msg lengths */ - update_header(&header, cred_len, msg_len); + update_header(&header, msg_len); + /* repack updated header */ tmp_len = get_buf_offset(buffer); set_buf_offset(buffer, 0); @@ -763,8 +761,9 @@ int slurm_send_recv_controller_msg(slurm_msg_t * request_msg, int error_code = 0; /* init message connection for communication with controller */ - if ((sockfd = slurm_open_controller_conn()) == SLURM_SOCKET_ERROR) + if ((sockfd = slurm_open_controller_conn()) == SLURM_SOCKET_ERROR) { return SLURM_SOCKET_ERROR; + } /* send request message */ if ((rc = @@ -913,6 +912,6 @@ int slurm_send_only_node_msg(slurm_msg_t * request_msg) /* Slurm message functions */ void slurm_free_msg(slurm_msg_t * msg) { - slurm_auth_free_credentials((slurm_auth_t) msg->cred); + g_slurm_auth_free(msg->cred); xfree(msg); } diff --git a/src/common/slurm_protocol_defs.h b/src/common/slurm_protocol_defs.h index b52c6900113ef957a332d95282ee8ffa4155b9c6..683830813bbc0357ff658626b54d016464dab247 100644 --- a/src/common/slurm_protocol_defs.h +++ b/src/common/slurm_protocol_defs.h @@ -159,8 +159,6 @@ typedef struct slurm_protocol_config { typedef struct slurm_protocol_header { uint16_t version; uint16_t flags; - slurm_credential_type_t cred_type; - uint32_t cred_length; slurm_msg_type_t msg_type; uint32_t body_length; } header_t; @@ -176,9 +174,7 @@ typedef struct slurm_msg { slurm_msg_type_t msg_type; slurm_addr address; slurm_fd conn_fd; - slurm_credential_type_t cred_type; void *cred; - uint32_t cred_size; void *data; uint32_t data_size; } slurm_msg_t; diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c index d94ac91032b5736aca654306719902701cd597e0..135da5dcdc6c0339d1db01d3a4aaaa0c2f044b75 100644 --- a/src/common/slurm_protocol_pack.c +++ b/src/common/slurm_protocol_pack.c @@ -209,9 +209,6 @@ pack_header(header_t * header, Buf buffer) { pack16(header->version, buffer); pack16(header->flags, buffer); - pack16((uint16_t) header->cred_type, buffer); - - pack32(header->cred_length, buffer); pack16((uint16_t) header->msg_type, buffer); pack32(header->body_length, buffer); } @@ -231,10 +228,6 @@ unpack_header(header_t * header, Buf buffer) safe_unpack16(&header->version, buffer); safe_unpack16(&header->flags, buffer); safe_unpack16(&tmp, buffer); - header->cred_type = (slurm_credential_type_t) tmp; - - safe_unpack32(&header->cred_length, buffer); - safe_unpack16(&tmp, buffer); header->msg_type = (slurm_msg_type_t) tmp; safe_unpack32(&header->body_length, buffer); return SLURM_SUCCESS; diff --git a/src/common/slurm_protocol_util.c b/src/common/slurm_protocol_util.c index af8a995d9f83b6726df3f036332e558a0bcfe656..c7f78673905f3e8e87861ab5dda23e8a19bcc948 100644 --- a/src/common/slurm_protocol_util.c +++ b/src/common/slurm_protocol_util.c @@ -65,15 +65,12 @@ void init_header(header_t * header, slurm_msg_type_t msg_type, } /* - * update_header - update a message header with the credential and message len + * update_header - update a message header with the message len * OUT header - the message header to update - * IN cred_length - credential length * IN msg_length - length of message to be send */ -void update_header(header_t * header, uint32_t cred_length, - uint32_t msg_length) +void update_header(header_t * header, uint32_t msg_length) { - header->cred_length = cred_length; header->body_length = msg_length; } diff --git a/src/common/slurm_protocol_util.h b/src/common/slurm_protocol_util.h index 7b73f9d171a12b968912ebe012d4f262c47ca106..8150009e23d071c9be40aceb39c58bf81136a660 100644 --- a/src/common/slurm_protocol_util.h +++ b/src/common/slurm_protocol_util.h @@ -87,13 +87,12 @@ init_io_stream_header(slurm_io_stream_header_t * header, char *key, uint32_t task_id, uint16_t type); /* - * update_header - update a message header with the credential and message len + * update_header - update a message header with the message len * OUT header - the message header to update - * IN cred_length - credential length * IN msg_length - length of message to be send */ extern void -update_header(header_t * header, uint32_t cred_length, uint32_t msg_length); +update_header(header_t * header, uint32_t msg_length); /* * read an i/o stream header from the supplied slurm stream diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..051a35a8f68b8fe512143219d0c45a7719853f01 --- /dev/null +++ b/src/plugins/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = auth + diff --git a/src/plugins/auth/Makefile.am b/src/plugins/auth/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..257e005e7e15fdda43fddf1141e55a57354c9ecc --- /dev/null +++ b/src/plugins/auth/Makefile.am @@ -0,0 +1,22 @@ +# $Id$ +# Makefile for auth plugins + +AUTOMAKE_OPTIONS = foreign + +PLUGIN_FLAGS = -module -avoid-version + +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common + +# Add your plugin to this line, following the naming conventions. +lib_LTLIBRARIES = libauth_none.la libauth_authd.la + +# Null authentication plugin. +libauth_none_la_SOURCES = auth_none.c +libauth_none_la_LDFLAGS = $(PLUGIN_FLAGS) +libauth_none_la_LIBADD = -lslurm + +# Authd authentication plugin -- requires libauth +libauth_authd_la_SOURCES = auth_authd.c +libauth_authd_la_LDFLAGS = $(PLUGIN_FLAGS) +libauth_authd_la_LIBADD = -lslurm -lauth + diff --git a/src/plugins/auth/auth_authd.c b/src/plugins/auth/auth_authd.c new file mode 100644 index 0000000000000000000000000000000000000000..0193f1a8d124865d4a32faac2b3cf1d88881be93 --- /dev/null +++ b/src/plugins/auth/auth_authd.c @@ -0,0 +1,347 @@ +/*****************************************************************************\ + * auth_authd - plugin for Brent Chun's authd + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Kevin Tew <tew1@llnl.gov> et. al. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * 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. + * + * 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 SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#if HAVE_CONFIG_H +# include "config.h" +# if HAVE_SSL +# include <openssl/rsa.h> +# include <openssl/pem.h> +# include <openssl/err.h> +# endif /* HAVE_SSL*/ +# if STDC_HEADERS +# include <stdio.h> +# include <string.h> +# endif /* STDC_HEADERS */ +# if HAVE_UNISTD_H +# include <unistd.h> +# endif /* HAVE_UNISTD_H */ +#else /* ! HAVE_CONFIG_H */ +# include <stdio.h> +# include <unistd.h> +# include <string.h> +# include <openssl/rsa.h> +# include <openssl/pem.h> +# include <openssl/err.h> +# include <auth.h> +#endif /* HAVE_CONFIG_H */ + +#include <pwd.h> +#include <grp.h> +#include <auth.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +/* Need these regardless of how main SLURM transport is abstracted. */ +#include <sys/socket.h> +#include <sys/un.h> + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 /* Cribbed from linux/un.h */ +#endif + +#include <slurm/slurm_errno.h> +#include "src/common/xmalloc.h" +#include "src/common/xassert.h" +#include "src/common/pack.h" +#include "src/common/log.h" + +const char plugin_name[] = "Brett Chun's authd authentication plugin"; +const char plugin_type[] = "auth/authd"; +const uint32_t plugin_version = 90; + +typedef struct _slurm_auth_credential { + credentials cred; + signature sig; +} slurm_auth_credential_t; + +/* + * These come from /usr/include/auth.h which should be installed + * as part of the authd installation. + */ +static char *cli_path = AUTH_SOCK_PATH; +static char *svr_path = AUTHD_SOCK_PATH; +static char *pub_key_file = AUTH_PUB_KEY; + +/* + * Write bytes reliably to a file descriptor. + */ +static int +write_bytes( int fd, char *buf, size_t size ) +{ + ssize_t bytes_remaining, bytes_written; + char *ptr; + + bytes_remaining = size; + ptr = buf; + while ( bytes_remaining > 0 ) { + bytes_written = write( fd, ptr, size ); + if ( bytes_written < 0 ) return -1; + bytes_remaining -= bytes_written; + ptr += bytes_written; + } + return 0; +} + +/* + * Read bytes reliably from a file descriptor. + */ +static int +read_bytes( int fd, char *buf, size_t size ) +{ + ssize_t bytes_remaining, bytes_read; + char *ptr; + + bytes_remaining = size; + ptr = buf; + while ( bytes_remaining > 0 ) { + bytes_read = read( fd, ptr, size ); + if ( bytes_read < 0 ) return -1; + bytes_remaining -= bytes_read; + ptr += bytes_read; + } + return 0; +} + +/* + * These two cribbed from auth.c in the authd distribution. They would + * normally be available in the authd library, but the library relies on + * Brett Chun's enormous and irrelevant convenience library, and we only + * need to make one call to that library here. So we inline the code + * from his library and sever the dependency. + */ +static int +slurm_auth_get_signature( credentials *cred, signature *sig ) +{ + int sock; + char cli_name[ UNIX_PATH_MAX ]; + struct sockaddr_un cli_addr; + struct sockaddr_un svr_addr; + socklen_t addr_len = sizeof( struct sockaddr_un ); + + if ( ( sock = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) { + return -1; + } + + cli_addr.sun_family = AF_UNIX; + memset( cli_addr.sun_path, 0, UNIX_PATH_MAX ); + sprintf( cli_name, cli_path, getpid() ); + strcpy( &cli_addr.sun_path[ 1 ], cli_name ); + if ( bind( sock, (struct sockaddr *) &cli_addr, addr_len ) < 0 ) { + error( "authd plugin: cannot bind socket to authd" ); + close( sock ); + return -1; + } + + svr_addr.sun_family = AF_UNIX; + memset( svr_addr.sun_path, 0, UNIX_PATH_MAX ); + strcpy( &svr_addr.sun_path[ 1 ], svr_path ); + if ( connect( sock, (struct sockaddr *) &svr_addr, addr_len ) < 0 ) { + error( "suthd plugin: cannot connect to authd" ); + close( sock ); + return -1; + } + + if ( write_bytes( sock, (char *) cred, sizeof( credentials ) ) < 0 ) { + error( "authd plugin: cannot write to authd" ); + close( sock ); + return -1; + } + if ( read_bytes( sock, (char *) sig, sizeof( signature ) ) < 0 ) { + error( "authd plugin: cannot read from authd" ); + close( sock ); + return -1; + } + close( sock ); + return 0; +} + +static int +slurm_auth_verify_signature( credentials *cred, signature *sig ) +{ + int rc_error = 0; + RSA *pub_key = NULL; + FILE *f = NULL; + + if ( ( f = fopen( pub_key_file, "r" ) ) == NULL ) { + rc_error = -1; + error( "authd plugin: cannot open public key file %s", pub_key_file ); + goto cleanup; + } + + if ( ( pub_key = PEM_read_RSA_PUBKEY( f, NULL, NULL, NULL ) ) == NULL ) { + error( "authd plugin: cannot read RSA public key" ); + rc_error = -1; + goto cleanup; + } + + ERR_load_crypto_strings(); + if ( RSA_verify( 0, + (unsigned char *) cred, sizeof( credentials ), + sig->data, AUTH_RSA_SIGLEN, + pub_key ) == 0 ) { + rc_error = -1; + error( "authd plugin: cannot verify signature" ); + goto cleanup; + } + + cleanup: + if ( pub_key != NULL ) RSA_free( pub_key ); + if ( f != NULL ) fclose( f ); + return rc_error; +} + +slurm_auth_credential_t * +slurm_auth_alloc( void ) +{ + return (slurm_auth_credential_t *) xmalloc( sizeof( slurm_auth_credential_t ) ); +} + +void +slurm_auth_free( slurm_auth_credential_t *cred ) +{ + if ( cred != NULL ) xfree( cred ); +} + +int +slurm_auth_activate( slurm_auth_credential_t *cred, int ttl ) +{ + if ( cred == NULL ) return SLURM_ERROR; + if ( ttl < 1 ) return SLURM_ERROR; + + /* Initialize credential with our user and group. */ + cred->cred.uid = geteuid(); + cred->cred.gid = getegid(); + + /* Set a valid time interval. */ + cred->cred.valid_from = time( NULL ); + cred->cred.valid_to = cred->cred.valid_from + ttl; + + /* Sign the credential. */ + if ( slurm_auth_get_signature( &cred->cred, &cred->sig ) < 0 ) { + return SLURM_ERROR; + } + + return SLURM_SUCCESS; +} + +int +slurm_auth_verify( slurm_auth_credential_t *cred ) +{ + int rc; + + if ( cred == NULL ) return SLURM_ERROR; + + rc = slurm_auth_verify_signature( &cred->cred, &cred->sig ); + if ( rc < 0 ) { + return SLURM_ERROR; + } + + return SLURM_SUCCESS; +} + + +uid_t +slurm_auth_get_uid( slurm_auth_credential_t *cred ) +{ + xassert( cred ); + return cred->cred.uid; +} + + +gid_t +slurm_auth_get_gid( slurm_auth_credential_t *cred ) +{ + xassert( cred ); + return cred->cred.gid; +} + + +void +slurm_auth_pack( slurm_auth_credential_t *cred, Buf buf ) +{ + uint16_t sig_size = sizeof( signature ); + + if ( ( cred == NULL ) || ( buf == NULL ) ) return; + + /* + * Marshall the plugin type for runtime sanity check. + * Add the terminating zero so we get it for free at the + * other end. + */ + packmem( (char *) plugin_type, strlen( plugin_type ) + 1, buf ); + + pack32( cred->cred.uid, buf ); + pack32( cred->cred.gid, buf ); + pack_time( cred->cred.valid_from, buf ); + pack_time( cred->cred.valid_to, buf ); + packmem( cred->sig.data, sig_size, buf ); +} + + +int +slurm_auth_unpack( slurm_auth_credential_t *cred, Buf buf ) +{ + uint16_t sig_size; /* ignored */ + char *data; + + if ( ( cred == NULL) || ( buf == NULL ) ) + return SLURM_ERROR; + + /* Check the plugin type. */ + unpackmem_ptr( &data, &sig_size, buf ); + if ( strcmp( data, plugin_type ) != 0 ) { + error( "authd plugin: authentication mismatch, got %s", data ); + return SLURM_ERROR; + } + + unpack32( &cred->cred.uid, buf ); + unpack32( &cred->cred.gid, buf ); + unpack_time( &cred->cred.valid_from, buf ); + unpack_time( &cred->cred.valid_to, buf ); + unpackmem_ptr( &data, &sig_size, buf ); + memcpy( cred->sig.data, data, sizeof( signature ) ); + + return SLURM_SUCCESS; +} + + +void +slurm_auth_print( slurm_auth_credential_t *cred, FILE *fp ) +{ + if ( cred == NULL ) return; + + verbose( "BEGIN AUTHD CREDENTIAL\n" ); + verbose( " UID: %d", cred->cred.uid ); + verbose( " GID: %d", cred->cred.gid ); + verbose( " Valid from: %s", ctime( &cred->cred.valid_from ) ); + verbose( " Valid to: %s", ctime( &cred->cred.valid_to ) ); + verbose( " Signature: 0x%02x%02x%02x%02x ...\n", + cred->sig.data[ 0 ], cred->sig.data[ 1 ], + cred->sig.data[ 2 ], cred->sig.data[ 3 ] ); + verbose( "END AUTHD CREDENTIAL\n" ); +} + diff --git a/src/plugins/auth/auth_none.c b/src/plugins/auth/auth_none.c new file mode 100644 index 0000000000000000000000000000000000000000..d80ab47f0022c34a74069276a2a5bdc3a27a018f --- /dev/null +++ b/src/plugins/auth/auth_none.c @@ -0,0 +1,296 @@ +/*****************************************************************************\ + * auth_none.c - NO-OP slurm authentication plugin, validates all users. + ***************************************************************************** + * Copyright (C) 2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Kevin Tew <tew1@llnl.gov> et. al. + * UCRL-CODE-2002-040. + * + * This file is part of SLURM, a resource management program. + * For details, see <http://www.llnl.gov/linux/slurm/>. + * + * 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. + * + * 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 SLURM; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + +#if HAVE_CONFIG_H +# include "config.h" +# if STDC_HEADERS +# include <string.h> +# endif +# if HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif /* HAVE_SYS_TYPES_H */ +# if HAVE_UNISTD_H +# include <unistd.h> +# endif +# if HAVE_INTTYPES_H +# include <inttypes.h> +# else /* ! HAVE_INTTYPES_H */ +# if HAVE_STDINT_H +# include <stdint.h> +# endif +# endif /* HAVE_INTTYPES_H */ +#else /* ! HAVE_CONFIG_H */ +# include <sys/types.h> +# include <unistd.h> +# include <stdint.h> +# include <string.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> + +#include <slurm/slurm_errno.h> +#include "src/common/xassert.h" +#include "src/common/xmalloc.h" +#include "src/common/pack.h" +#include "src/common/log.h" +#include "src/common/slurm_auth.h" + +/* + * These variables are required by the generic plugin interface. If they + * are not found in the plugin, the plugin loader will ignore it. + * + * plugin_name - a string giving a human-readable description of the + * plugin. There is no maximum length, but the symbol must refer to + * a valid string. + * + * plugin_type - a string suggesting the type of the plugin or its + * applicability to a particular form of data or method of data handling. + * If the low-level plugin API is used, the contents of this string are + * unimportant and may be anything. SLURM uses the higher-level plugin + * interface which requires this string to be of the form + * + * <application>/<method> + * + * where <application> is a description of the intended application of + * the plugin (e.g., "auth" for SLURM authentication) and <method> is a + * description of how this plugin satisfies that application. SLURM will + * only load authentication plugins if the plugin_type string has a prefix + * of "auth/". + * + * plugin_version - an unsigned 32-bit integer giving the version number + * of the plugin. If major and minor revisions are desired, the major + * version number may be multiplied by a suitable magnitude constant such + * as 100 or 1000. Various SLURM versions will likely require a certain + * minimum versions for their plugins as the authentication API matures. + */ +const char plugin_name[] = "Null authentication plugin"; +const char plugin_type[] = "auth/none"; +const uint32_t plugin_version = 90; + + +/* + * An opaque type representing authentication credentials. This type can be + * called whatever is meaningful and may contain any data required by the + * plugin. However, the plugin must be able to recover the Linux UID and + * GID given only an object of this type. + * + * Since no verification of the credentials is performed in the "none" + * authentication, this plugin simply uses the system-supplied UID and GID. + * In a more robust authentication context, this might include tickets or + * other signatures which the functions of this API can use to conduct + * verification. + * + * The client code never sees the inside of this structure directly. + * Objects of this type are passed in and out of the plugin via + * anonymous pointers. Because of this, robust plugins may wish to add + * some form of runtime typing to ensure that the pointers they have + * received are actually appropriate credentials and not pointers to + * random memory. + */ +typedef struct _slurm_auth_credential { + uid_t uid; + gid_t gid; +} slurm_auth_credential_t; + +void init ( void ) +{ + printf( "hello\n" ); +} + +/* + * The remainder of this file implements the standard SLURM authentication + * API. + */ + +/* + * Allocate a credential. This function should return NULL if it cannot + * allocate a credential. Whether the credential is populated with useful + * data at this time is implementation-dependent. + */ +slurm_auth_credential_t * +slurm_auth_alloc( void ) +{ + return (slurm_auth_credential_t *) xmalloc( sizeof( slurm_auth_credential_t ) ); +} + +/* + * Free a credential that was allocated with slurm_auth_alloc(). + */ +void +slurm_auth_free( slurm_auth_credential_t *cred ) +{ + if ( cred != NULL ) xfree( cred ); +} + +/* + * Prepare a credential for use as an authentication token. Accessor + * functions (slurm_auth_get_uid() and slurm_auth_get_gid()) are not required + * to return valid data until this function has been called successfully + * for the credential. + * + * secs - the number of seconds for which this credential is deemed + * valid; not appropriate to this plugin but essential to others. + * + * Return SLURM_SUCCESS if the credential is successfully activated. + */ +int +slurm_auth_activate( slurm_auth_credential_t *cred, int secs ) +{ + if ( cred == NULL ) return SLURM_ERROR; + cred->uid = geteuid(); + cred->gid = getegid(); + return SLURM_SUCCESS; +} + +/* + * Verify a credential to approve or deny authentication. + * + * Return SLURM_SUCCESS if the credential is in order and valid. + */ +int +slurm_auth_verify( slurm_auth_credential_t *cred ) +{ + return SLURM_SUCCESS; +} + +/* + * Obtain the Linux UID from the credential. The accuracy of this data + * is not assured until slurm_auth_activate() and slurm_auth_verify() + * have been called for it in that order. A plugin may choose to + * enforce this call order by adding bookkeeping to its implementation + * of slurm_auth_credential_t, but SLURM will guarantee to issue the + * proper sequence of calls. + */ +uid_t +slurm_auth_get_uid( slurm_auth_credential_t *cred ) +{ + if ( cred == NULL ) { + return SLURM_AUTH_NOBODY; + } else { + return cred->uid; + } +} + +/* + * Obtain the Linux GID from the credential. See slurm_auth_get_uid() + * above for details on correct behavior. + */ +gid_t +slurm_auth_get_gid( slurm_auth_credential_t *cred ) +{ + if ( cred == NULL ) { + return SLURM_AUTH_NOBODY; + } else { + return cred->gid; + } +} + +/* + * Marshall a credential for transmission over the network, according to + * SLURM's marshalling protocol. + */ +void +slurm_auth_pack( slurm_auth_credential_t *cred, Buf buf ) +{ + if ( ( cred == NULL ) || ( buf == NULL ) ) { + error( "malformed slurm_auth_pack call in auth/none plugin" ); + return; + } + + /* + * Prefix the credential with a description of the credential + * type so that it can be sanity-checked at the receiving end. + */ + packmem( (char *) plugin_type, strlen( plugin_type ) + 1, buf ); + /* + * Pack the data values. + */ + pack32( cred->uid, buf ); + pack32( cred->gid, buf ); +} + +/* + * Unmarshall a credential after transmission over the network according + * to SLURM's marshalling protocol. + */ +int +slurm_auth_unpack( slurm_auth_credential_t *cred, Buf buf ) +{ + char *tmpstr; + int32_t tmpint; + uint16_t size; + + if ( ( cred == NULL ) || ( buf == NULL ) ) { + error( "malformed slurm_auth_unpack call in auth/none plugin" ); + return SLURM_ERROR; + } + + /* + * Get the authentication type. + */ + if ( unpackmem_ptr( &tmpstr, &size, buf ) != SLURM_SUCCESS ) { + error( "cannot unpack authentication type: %m" ); + return SLURM_ERROR; + } + if ( strcmp( tmpstr, plugin_type ) != 0 ) { + error( "runtime authentication plugin type mismatch" ); + error( "plugin expected 'auth/none' and got '%s'", tmpstr ); + return SLURM_ERROR; + } + + /* + * We do it the hard way because we don't know anything about the + * size of uid_t or gid_t, only that they are integer values. We + * pack them as 32-bit integers, but we can't pass addresses to them + * directly to unpack as 32-bit integers because there will be bad + * clobbering if they really aren't. This technique ensures a + * warning at compile time if the sizes are incompatible. + */ + if ( unpack32( &tmpint, buf ) != SLURM_SUCCESS ) return SLURM_ERROR; + cred->uid = tmpint; + if ( unpack32( &tmpint, buf ) != SLURM_SUCCESS ) return SLURM_ERROR; + cred->gid = tmpint; + + return SLURM_SUCCESS; +} + +/* + * Print to a stdio stream a human-readable representation of the + * credential for debugging or logging purposes. The format is left + * to the imagination of the plugin developer. + */ +void +slurm_auth_print( slurm_auth_credential_t *cred, FILE *fp ) +{ + if ( ( cred == NULL) || ( fp == NULL ) ) { + return; + } + + printf( "BEGIN SLURM BASIC AUTHENTICATION CREDENTIAL\n" ); + printf( "\tUID = %d\n", cred->uid ); + printf( "\tGID = %d\n", cred->gid ); + printf( "END SLURM BASIC AUTHENTICATION CREDENTIAL\n" ); +} diff --git a/src/slurmctld/Makefile.am b/src/slurmctld/Makefile.am index 59e819629fc622f60168307d3a3e3bad3cfbb284..1b2a6a99d82a3dcae98510afcda63574592852b9 100644 --- a/src/slurmctld/Makefile.am +++ b/src/slurmctld/Makefile.am @@ -31,6 +31,8 @@ slurmctld_SOURCES = \ read_config.c \ step_mgr.c +slurmctld_LDFLAGS = -export-dynamic + force: $(slurmctld_LDADD) : force @cd `dirname $@` && $(MAKE) `basename $@` diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 9afc0de902088f53ab9b145cf357bac9f468646a..920dd1953750f20bc3f69837a3e732cd4c33cbd0 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -465,7 +465,7 @@ static void *_service_connection(void *arg) if ((error_code = slurm_receive_msg(newsockfd, msg)) == SLURM_SOCKET_ERROR) { - error("slurm_receive_msg error %m"); + error("slurm_receive_msg (_service_connection) error %m"); } else { if (msg->msg_type == REQUEST_SHUTDOWN_IMMEDIATE) return_code = (void *) "fini"; @@ -956,7 +956,7 @@ static void _slurm_rpc_job_step_kill(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: REQUEST_CANCEL_JOB_STEP"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); lock_slurmctld(job_write_lock); /* do RPC call */ @@ -1027,7 +1027,7 @@ static void _slurm_rpc_job_step_complete(slurm_msg_t * msg) /* init */ start_time = clock(); debug("Processing RPC: REQUEST_COMPLETE_JOB_STEP"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); lock_slurmctld(job_write_lock); /* do RPC call */ @@ -1193,7 +1193,7 @@ static void _slurm_rpc_update_job(slurm_msg_t * msg) unlock_slurmctld(job_write_lock); /* do RPC call */ - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); error_code = update_job(job_desc_msg, uid); /* return result */ @@ -1231,7 +1231,7 @@ static void _slurm_rpc_update_node(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: REQUEST_UPDATE_NODE"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; error("Security violation, UPDATE_NODE RPC from uid %u", @@ -1282,7 +1282,7 @@ static void _slurm_rpc_update_partition(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: REQUEST_UPDATE_PARTITION"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; error @@ -1338,7 +1338,7 @@ static void _slurm_rpc_submit_batch_job(slurm_msg_t * msg) /* do RPC call */ dump_job_desc(job_desc_msg); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != job_desc_msg->user_id) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; @@ -1402,7 +1402,7 @@ static void _slurm_rpc_allocate_resources(slurm_msg_t * msg) /* do RPC call */ dump_job_desc(job_desc_msg); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != job_desc_msg->user_id) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; @@ -1475,7 +1475,7 @@ static void _slurm_rpc_allocate_and_run(slurm_msg_t * msg) /* do RPC call */ dump_job_desc(job_desc_msg); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != job_desc_msg->user_id) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; @@ -1575,7 +1575,7 @@ static void _slurm_rpc_old_job_alloc(slurm_msg_t * msg) debug("Processing RPC: REQUEST_OLD_JOB_RESOURCE_ALLOCATION"); /* do RPC call */ - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != job_desc_msg->uid) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; error("Security violation, RESOURCE_ALLOCATE from uid %u", @@ -1643,7 +1643,7 @@ static void _slurm_rpc_job_will_run(slurm_msg_t * msg) /* do RPC call */ dump_job_desc(job_desc_msg); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != job_desc_msg->user_id) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; @@ -1678,7 +1678,7 @@ static void _slurm_rpc_ping(slurm_msg_t * msg) { /* init */ int error_code = SLURM_SUCCESS; - uid_t uid = slurm_auth_uid(msg->cred); + uid_t uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error("Security violation, PING RPC from uid %u", @@ -1706,7 +1706,7 @@ static void _slurm_rpc_reconfigure_controller(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: REQUEST_RECONFIGURE"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error("Security violation, RECONFIGURE RPC from uid %u", (unsigned int) uid); @@ -1761,7 +1761,7 @@ static void _slurm_rpc_shutdown_controller(slurm_msg_t * msg) READ_LOCK, NO_LOCK }; - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error("Security violation, SHUTDOWN RPC from uid %u", (unsigned int) uid); @@ -1814,7 +1814,7 @@ static void _slurm_rpc_shutdown_controller_immediate(slurm_msg_t * msg) int error_code = 0; uid_t uid; - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error ("Security violation, SHUTDOWN_IMMEDIATE RPC from uid %u", @@ -1850,7 +1850,7 @@ static void _slurm_rpc_job_step_create(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: REQUEST_JOB_STEP_CREATE"); dump_step_desc(req_step_msg); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != req_step_msg->user_id) && (uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; @@ -1916,7 +1916,7 @@ static void _slurm_rpc_node_registration(slurm_msg_t * msg) start_time = clock(); debug("Processing RPC: MESSAGE_NODE_REGISTRATION_STATUS"); - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error_code = ESLURM_USER_ID_MISSING; error("Security violation, NODE_REGISTER RPC from uid %u", @@ -2302,7 +2302,7 @@ static int _background_process_msg(slurm_msg_t * msg) int error_code = 0; uid_t uid; - uid = slurm_auth_uid(msg->cred); + uid = g_slurm_auth_get_uid(msg->cred); if ((uid != 0) && (uid != getuid())) { error("Security violation, SHUTDOWN RPC from uid %u", (unsigned int) uid); diff --git a/src/slurmd/Makefile.am b/src/slurmd/Makefile.am index 84514f662dc52cd7a79f58de30fbb6296f14683e..8f48ad9b8782f3d9eb3e10ea2d688008888c2435 100644 --- a/src/slurmd/Makefile.am +++ b/src/slurmd/Makefile.am @@ -22,7 +22,7 @@ slurmd_LDADD = \ $(top_builddir)/src/common/libeio.la \ $(SSL_LIBS) - + common_sources = \ slurmd.c slurmd.h \ req.c req.h \ @@ -42,6 +42,8 @@ common_sources = \ slurmd_SOURCES = $(common_sources) $(interconnect_sources) +slurmd_LDFLAGS = -export-dynamic + EXTRA_slurmd_SOURCES = no_interconnect.c elan_interconnect.c force: diff --git a/src/slurmd/req.c b/src/slurmd/req.c index 3c24fca3062db3e811a3ae1e00eaa48cb70c34df..73a3bfcdc65901484221eb8fabc98751f6de262f 100644 --- a/src/slurmd/req.c +++ b/src/slurmd/req.c @@ -204,7 +204,7 @@ _rpc_launch_tasks(slurm_msg_t *msg, slurm_addr *cli) bool super_user = false, run_prolog = false; launch_tasks_request_msg_t *req = msg->data; - req_uid = slurm_auth_uid(msg->cred); + req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid == conf->slurm_user_id) || (req_uid == 0)) super_user = true; if ((super_user == false) && (req_uid != req->uid)) { @@ -255,7 +255,7 @@ _rpc_batch_job(slurm_msg_t *msg, slurm_addr *cli) { batch_job_launch_msg_t *req = (batch_job_launch_msg_t *)msg->data; int rc = SLURM_SUCCESS; - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { error("Security violation, batch launch RPC from uid %u", @@ -286,7 +286,7 @@ _rpc_batch_job(slurm_msg_t *msg, slurm_addr *cli) static void _rpc_reconfig(slurm_msg_t *msg, slurm_addr *cli_addr) { - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { error("Security violation, reconfig RPC from uid %u", @@ -299,7 +299,7 @@ _rpc_reconfig(slurm_msg_t *msg, slurm_addr *cli_addr) static void _rpc_shutdown(slurm_msg_t *msg, slurm_addr *cli_addr) { - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { error("Security violation, shutdown RPC from uid %u", @@ -313,7 +313,7 @@ static int _rpc_ping(slurm_msg_t *msg, slurm_addr *cli_addr) { int rc = SLURM_SUCCESS; - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { error("Security violation, ping RPC from uid %u", @@ -341,7 +341,7 @@ _rpc_kill_tasks(slurm_msg_t *msg, slurm_addr *cli_addr) goto done; } - req_uid = slurm_auth_uid(msg->cred); + req_uid = g_slurm_auth_get_uid(msg->cred); if ((req_uid != step->uid) && (req_uid != 0)) { debug("kill req from uid %ld for job %d.%d owned by uid %ld", req_uid, req->job_id, req->job_step_id, step->uid); @@ -429,8 +429,8 @@ _rpc_reattach_tasks(slurm_msg_t *msg, slurm_addr *cli) memset(&resp, 0, sizeof(reattach_tasks_response_msg_t)); slurm_get_addr(cli, &port, host, sizeof(host)); - req_uid = slurm_auth_uid(msg->cred); - req_gid = slurm_auth_gid(msg->cred); + req_uid = g_slurm_auth_get_uid(msg->cred); + req_gid = g_slurm_auth_get_gid(msg->cred); info("reattach request from %ld@%s for %d.%d", req_uid, host, req->job_id, req->job_step_id); @@ -545,8 +545,8 @@ _job_still_running(uint32_t job_id) static void _rpc_revoke_credential(slurm_msg_t *msg, slurm_addr *cli) { - int rc = SLURM_SUCCESS; - uid_t req_uid = slurm_auth_uid(msg->cred); + int rc = SLURM_SUCCESS; + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); revoke_credential_msg_t *req = (revoke_credential_msg_t *) msg->data; if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { @@ -593,7 +593,7 @@ static void _rpc_update_time(slurm_msg_t *msg, slurm_addr *cli) { int rc = SLURM_SUCCESS; - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); job_time_msg_t *req = (job_time_msg_t *) msg->data; if ((req_uid != conf->slurm_user_id) && (req_uid != 0)) { diff --git a/src/slurmd/slurmd.c b/src/slurmd/slurmd.c index 9563e9c1a8b132c5f4fb6a544b6767f101d89b24..1b5b3bb639a1f70090b934d8fe0714e82875aa27 100644 --- a/src/slurmd/slurmd.c +++ b/src/slurmd/slurmd.c @@ -168,8 +168,10 @@ main (int argc, char *argv[]) info("%s started on %T", xbasename(argv[0])); - if (_slurmd_init() < 0) + if (_slurmd_init() < 0) { + error( "slurmd initialization failed" ); exit(1); + } if (send_registration_msg(SLURM_SUCCESS) < 0) error("Unable to register with slurm controller"); diff --git a/src/srun/msg.c b/src/srun/msg.c index 9f9de7dae7cd26504990a4c347f5e973f892b612..090128632921c0ead25acab27cd4e5e91cc4e2b4 100644 --- a/src/srun/msg.c +++ b/src/srun/msg.c @@ -426,7 +426,7 @@ _exit_handler(job_t *job, slurm_msg_t *exit_msg) static void _handle_msg(job_t *job, slurm_msg_t *msg) { - uid_t req_uid = slurm_auth_uid(msg->cred); + uid_t req_uid = g_slurm_auth_get_uid(msg->cred); uid_t uid = getuid(); if ((req_uid != slurm_uid) && (req_uid != 0) && (req_uid != uid)) {