diff --git a/src/common/Makefile.am b/src/common/Makefile.am index c07cdf70918ddaa4dbc972f27fae5c7838d3ee8a..6b452b303a949b5b64fc1a3b6142e5bd0d6908e1 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -52,6 +52,7 @@ libcommon_la_SOURCES = \ slurm_protocol_defs.h \ util-net.c util-net.h \ slurm_auth.c slurm_auth.h \ + arg_desc.c arg_desc.h \ macros.h \ $(elan_sources) diff --git a/src/common/arg_desc.c b/src/common/arg_desc.c new file mode 100644 index 0000000000000000000000000000000000000000..566ae5282542d0f2542a8ff56a4e478dd766e027 --- /dev/null +++ b/src/common/arg_desc.c @@ -0,0 +1,50 @@ +#include <string.h> +#include "src/common/arg_desc.h" +#include "src/common/xassert.h" + +const int +arg_count( const arg_desc_t *desc ) +{ + int i; + + if ( desc == NULL ) return 0; + + i = 0; + while ( desc[ i ].name != NULL ) ++i; + + return i; +} + + +const int +arg_idx_by_name( const arg_desc_t *desc, const char *name ) +{ + int i; + + if ( desc == NULL ) return -1; + if ( name == NULL ) return -1; + + for ( i = 0; desc[ i ].name != NULL; ++i ) { + if ( strcmp( desc[ i ].name, name ) == 0 ) { + return i; + } + } + + return -1; +} + + +const char * +arg_name_by_idx( const arg_desc_t *desc, const int idx ) +{ + int i = idx; + + if ( desc == NULL ) return NULL; + + while ( i > 0 ) { + if ( desc[ i ].name != NULL ) --i; + } + + return desc[ i ].name; +} + diff --git a/src/common/arg_desc.h b/src/common/arg_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..1de433503a8db131fd0335005e4728a482d9dde5 --- /dev/null +++ b/src/common/arg_desc.h @@ -0,0 +1,71 @@ +#ifndef __ARG_DESC_H__ +#define __ARG_DESC_H__ + +/* + * An argument descriptor is a named positional parameter in an + * argv-like vector of arguments. An array of named parameters + * constitutes the descriptor, and the index (zero-based) in the + * array of the named parameter is also its index in the argument + * vector. + * + * The descriptor array must be terminated by an entry whose name + * is the NULL pointer. + * + * arg_desc_t arg_desc[] = { + * { "foo" }, + * { "bar" }, + * { NULL } + * }; + * + * For vectors which are finalized at initialization, the receiving + * functions can call arg_idx_by_name() and cache the value in + * order to accelerate argument processing. + * + * For well-defined APIs containing explicit initialization routines, + * this can be done at initialization, as in + * + * void init( arg_desc_t *desc ) + * { + * static_foo_idx = arg_idx_by_name( desc, "foo" ); + * } + * + * void need_foo( void *argv[] ) + * { + * foo_type foo = (foo_type) argv[ static_foo_idx ]; + * ... + * } + * + * For vectors which may vary for each invocation of the function, + * it is best to pass the argument descriptor array as a first-class + * parameter to the function: + * + * void need_foo_dynamic( arg_desc_t *desc, void *argv[] ) + * { + * int idx = arg_idx_by_name( desc, "foo" ); + * foo_type foo = (foo_type) argv[ idx ]; + * } + */ + +typedef struct _arg_desc { + char *name; +} arg_desc_t; + +/* + * Return the number of argument names in the descriptor. + */ +const int arg_count( const arg_desc_t *desc ); + +/* + * Return the index in the descriptor corresponding to the name. + * + * Returns -1 if the name can't be found. + */ +const int arg_idx_by_name( const arg_desc_t *desc, const char *name ); + +/* + * Return the name of the argument for the given index, or NULL if + * the index is invalid. + */ +const char *arg_name_by_idx( const arg_desc_t *desc, const int idx ); + +#endif /*__ARG_DESC_H__*/ diff --git a/src/common/slurm_auth.c b/src/common/slurm_auth.c index d9d8222cf8e286d80e2c5e546f2d7f34e9ae1277..90ccebeaba5434718b8ab6c700f21b4acd11e295 100644 --- a/src/common/slurm_auth.c +++ b/src/common/slurm_auth.c @@ -37,6 +37,7 @@ #include "src/common/slurm_auth.h" #include "src/common/plugin.h" #include "src/common/plugrack.h" +#include "src/common/arg_desc.h" /* * WARNING: Do not change the order of these fields or add additional @@ -45,9 +46,9 @@ * end of the structure. */ typedef struct slurm_auth_ops { - void * (*create) ( void ); + void * (*create) ( void *argv[] ); int (*destroy) ( void *cred ); - int (*verify) ( void *cred ); + int (*verify) ( void *cred, void *argv[] ); uid_t (*get_uid) ( void *cred ); gid_t (*get_gid) ( void *cred ); int (*pack) ( void *cred, Buf buf ); @@ -94,6 +95,15 @@ static pthread_mutex_t context_lock = PTHREAD_MUTEX_INITIALIZER; static slurm_ctl_conf_t conf; static pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER; +/* + * Order of advisory arguments passed to some of the plugins. + */ +static arg_desc_t auth_args[] = { + { ARG_HOST_LIST }, + { ARG_TIMEOUT }, + { NULL } +}; + static char * get_plugin_dir( void ) @@ -182,6 +192,44 @@ slurm_auth_get_ops( slurm_auth_context_t c ) return &c->ops; } +const arg_desc_t * +slurm_auth_get_arg_desc( void ) +{ + return auth_args; +} + +void ** +slurm_auth_marshal_args( void *hosts, int timeout ) +{ + static int hostlist_idx = -1; + static int timeout_idx = -1; + static int count = sizeof( auth_args ) / sizeof( struct _arg_desc ) - 1; + void **argv; + + /* Get indices from descriptor, if we haven't already. */ + if ( ( hostlist_idx == -1 ) && + ( timeout_idx == -1 ) ) { + hostlist_idx = arg_idx_by_name( auth_args, ARG_HOST_LIST ); + timeout_idx = arg_idx_by_name( auth_args, ARG_TIMEOUT ); + } + + argv = xmalloc( count * sizeof( void * ) ); + + /* Marshal host list. Don't quite know how to do this yet. */ + argv[ hostlist_idx ] = hosts; + + /* Marshal timeout. */ + argv[ timeout_idx ] = (void *) timeout; + + return argv; +} + + +void slurm_auth_free_args( void **argv ) +{ + xfree( argv ); +} + slurm_auth_context_t slurm_auth_context_create( const char *auth_type ) @@ -298,12 +346,12 @@ slurm_auth_init( void ) */ void * -g_slurm_auth_create( void ) +g_slurm_auth_create( void *argv[] ) { if ( slurm_auth_init() < 0 ) return NULL; - return (*(g_context->ops.create))(); + return (*(g_context->ops.create))( argv ); } int @@ -316,12 +364,12 @@ g_slurm_auth_destroy( void *cred ) } int -g_slurm_auth_verify( void *cred ) +g_slurm_auth_verify( void *cred, void *argv[] ) { if ( slurm_auth_init() < 0 ) return SLURM_ERROR; - return (*(g_context->ops.verify))( cred ); + return (*(g_context->ops.verify))( cred, argv ); } uid_t diff --git a/src/common/slurm_auth.h b/src/common/slurm_auth.h index ddf2121a5c04b1c8cbc31e9dc2eccb1f08fb4ddf..91e8bb8a95a9b68c833064c46d00d5d23c2afdef 100644 --- a/src/common/slurm_auth.h +++ b/src/common/slurm_auth.h @@ -44,6 +44,7 @@ #include "src/common/plugrack.h" #include "src/common/pack.h" +#include "src/common/arg_desc.h" /* * This API operates on a global authentication @@ -62,17 +63,49 @@ * */ +/* + * General error codes that plugins (or the plugin system) can + * generate. Plugins may produce additional codes starting with + * SLURM_AUTH_FIRST_LOCAL_ERROR. They are responsible for providing + * text messages to accompany the codes. This API resolves string + * messages for these codes. + */ enum { - SLURM_AUTH_NOPLUGIN, - SLURM_AUTH_BADARG, - SLURM_AUTH_MEMORY, - SLURM_AUTH_NOUSER, - SLURM_AUTH_INVALID, - SLURM_AUTH_MISMATCH, - - SLURM_AUTH_FIRST_LOCAL_ERROR /* Always keep me last. */ + SLURM_AUTH_NOPLUGIN, /* No plugin for this type. */ + SLURM_AUTH_BADARG, /* Bad argument to an API func. */ + SLURM_AUTH_MEMORY, /* Problem allocating memory. */ + SLURM_AUTH_NOUSER, /* User not defined on host. */ + SLURM_AUTH_INVALID, /* Invalid credential. */ + SLURM_AUTH_MISMATCH, /* Credential from another plugin. */ + + SLURM_AUTH_FIRST_LOCAL_ERROR /* Always keep me last. */ }; +/* + * Text labels for advisory arguments passed to plugin functions. + * Use these labels rather than string literals in order to avoid + * misspellings. + */ +#define ARG_HOST_LIST "HostList" +#define ARG_TIMEOUT "Timeout" + +/* + * Return the argument descriptor for the argument vectors in the + * plugin API. + */ +const arg_desc_t *slurm_auth_get_arg_desc( void ); + +/* + * Marshal the arguments into a generic argument vector according to + * the authentication argument layout. + */ +void **slurm_auth_marshal_args( void *hosts, int timeout ); + +/* + * Free an argument list created by slurm_auth_marshal_args(). + */ +void slurm_auth_free_args( void **args ); + /* * SLURM authentication context opaque type. */ @@ -109,9 +142,9 @@ int slurm_auth_init( void ); /* * Static bindings for the global authentication context. */ -void *g_slurm_auth_create( void ); +void *g_slurm_auth_create( void *argv[] ); int g_slurm_auth_destroy( void *cred ); -int g_slurm_auth_verify( void *cred ); +int g_slurm_auth_verify( void *cred, void *argv[] ); uid_t g_slurm_auth_get_uid( void *cred ); gid_t g_slurm_auth_get_gid( void *cred ); int g_slurm_auth_pack( void *cred, Buf buf ); diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c index b27ad805f4ddfe6af769dccda5d148a7388e47b4..58ae8d4ac46130ae1e24d98de968570754f7d050 100644 --- a/src/common/slurm_protocol_api.c +++ b/src/common/slurm_protocol_api.c @@ -334,6 +334,7 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) int rc; void *auth_cred; Buf buffer; + void **argv; buftemp = xmalloc(SLURM_PROTOCOL_MAX_MESSAGE_BUFFER_SIZE); if ((rc = _slurm_msg_recvfrom(open_fd, buftemp, @@ -365,13 +366,21 @@ int slurm_receive_msg(slurm_fd open_fd, slurm_msg_t * msg) } /* verify credentials */ - if ((rc = g_slurm_auth_verify(auth_cred)) != SLURM_SUCCESS) { + argv = slurm_auth_marshal_args( NULL, 2 ); + if ( argv == NULL ) { + (void) g_slurm_auth_destroy( auth_cred ); + free_buf( buffer ); + slurm_seterrno_ret( SLURM_PROTOCOL_AUTHENTICATION_ERROR ); + } + rc = g_slurm_auth_verify( auth_cred, argv ); + slurm_auth_free_args( argv ); + if ( rc != SLURM_SUCCESS) { error( "authentication: %s ", g_slurm_auth_errstr( g_slurm_auth_errno( auth_cred ) ) ); (void) g_slurm_auth_destroy(auth_cred); free_buf(buffer); slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR); - } + } /* unpack msg body */ msg->msg_type = header.msg_type; @@ -430,9 +439,16 @@ int slurm_send_node_msg(slurm_fd open_fd, slurm_msg_t * msg) unsigned int msg_len, tmp_len; Buf buffer; void *auth_cred; + void **argv; /* initialize header */ - auth_cred = g_slurm_auth_create(); + argv = slurm_auth_marshal_args( NULL, 1 ); + if ( argv == NULL ) { + error( "cannot marshal arguments to create credential" ); + return SLURM_PROTOCOL_AUTHENTICATION_ERROR; + } + auth_cred = g_slurm_auth_create( argv ); + slurm_auth_free_args( argv ); if ( auth_cred == NULL ) { error( "authentication: %s", g_slurm_auth_errstr( g_slurm_auth_errno( NULL ) ) ); diff --git a/src/plugins/auth/auth_authd.c b/src/plugins/auth/auth_authd.c index f0bb01fcf6f5de36be371bf800c9c97a8b40f6a7..1bf933ba3afe478cfe717a5ca582607b7e13b34f 100644 --- a/src/plugins/auth/auth_authd.c +++ b/src/plugins/auth/auth_authd.c @@ -69,13 +69,20 @@ #include "src/common/xassert.h" #include "src/common/pack.h" #include "src/common/log.h" +#include "src/common/arg_desc.h" const char plugin_name[] = "Brett Chun's authd authentication plugin"; const char plugin_type[] = "auth/authd"; const uint32_t plugin_version = 90; -/* Default life span of an authd credential in seconds. */ -static const int authd_ttl = 2; +/* + * Where to find the timeout in the argument vector. This is set + * during initialization and should not change. + */ +static int timeout_idx = -1; + +/* Default timeout. */ +static const int AUTHD_TTL = 2; typedef struct _slurm_auth_credential { credentials cred; @@ -231,22 +238,47 @@ slurm_auth_verify_signature( credentials *cred, signature *sig ) return rc_error; } + +int init( void ) +{ + const arg_desc_t *desc; + + verbose( "authd authenticaiton module initializing" ); + + if ( ( desc = slurm_auth_get_arg_desc() ) == NULL ) { + error( "unable to query SLURM for argument vector layout" ); + return SLURM_ERROR; + } + + if ( ( timeout_idx = arg_idx_by_name( desc, ARG_TIMEOUT ) ) < 0 ) { + error( "Required argument 'Timeout' not provided" ); + return SLURM_ERROR; + } + + return SLURM_SUCCESS; +} + + slurm_auth_credential_t * -slurm_auth_create( void ) +slurm_auth_create( void *argv[] ) { - int ttl = authd_ttl; - slurm_auth_credential_t *cred = - (slurm_auth_credential_t *) + int ttl; + slurm_auth_credential_t *cred; + + if ( argv == NULL ) { + plugin_errno = SLURM_AUTH_MEMORY; + return NULL; + } + + cred = (slurm_auth_credential_t *) xmalloc( sizeof( slurm_auth_credential_t ) ); cred->cr_errno = SLURM_SUCCESS; - - /* 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 ); + ttl = timeout_idx >= 0 ? (int) argv[ timeout_idx ] : AUTHD_TTL; /* * In debug mode read the time-to-live from an environment * variable. @@ -260,7 +292,7 @@ slurm_auth_create( void ) } } #endif /*NDEBUG*/ - + cred->cred.valid_to = cred->cred.valid_from + ttl; /* Sign the credential. */ @@ -285,12 +317,12 @@ slurm_auth_destroy( slurm_auth_credential_t *cred ) } int -slurm_auth_verify( slurm_auth_credential_t *cred ) +slurm_auth_verify( slurm_auth_credential_t *cred, void *argv[] ) { int rc; time_t now; - if ( cred == NULL ) { + if ( ( cred == NULL ) || ( argv == NULL ) ) { plugin_errno = SLURM_AUTH_BADARG; return SLURM_ERROR; } diff --git a/src/plugins/auth/auth_munge.c b/src/plugins/auth/auth_munge.c index 2e8dc5ad953328f70ac2c5def9629c9eabfaa2d4..e532ee5fb229900be435fb5314b73e2775954941 100644 --- a/src/plugins/auth/auth_munge.c +++ b/src/plugins/auth/auth_munge.c @@ -62,6 +62,7 @@ #include "src/common/pack.h" #include "src/common/log.h" #include "src/common/slurm_auth.h" +#include "src/common/arg_desc.h" const char plugin_name[] = "auth plugin for Chris Dunlap's Munge"; const char plugin_type[] = "auth/munge"; @@ -69,6 +70,8 @@ const uint32_t plugin_version = 10; static int plugin_errno = SLURM_SUCCESS; +static int host_list_idx = -1; + enum { SLURM_AUTH_UNPACK = SLURM_AUTH_FIRST_LOCAL_ERROR }; @@ -120,12 +123,10 @@ _decode_cred(char *m, slurm_auth_credential_t *c) int init ( void ) { - /* - * Perhaps we could init a global context here? - * Do nothing for now. - * - */ - return 0; + host_list_idx = arg_idx_by_name( slurm_auth_get_arg_desc(), + ARG_HOST_LIST ); + if ( host_list_idx == -1 ) return SLURM_ERROR; + return SLURM_SUCCESS; } @@ -135,7 +136,7 @@ int init ( void ) * data at this time is implementation-dependent. */ slurm_auth_credential_t * -slurm_auth_create( void ) +slurm_auth_create( void *argv[] ) { slurm_auth_credential_t *cred = NULL; munge_err_t e = EMUNGE_SUCCESS; @@ -189,7 +190,7 @@ slurm_auth_destroy( slurm_auth_credential_t *cred ) * Return SLURM_SUCCESS if the credential is in order and valid. */ int -slurm_auth_verify( slurm_auth_credential_t *c ) +slurm_auth_verify( slurm_auth_credential_t *c, void *argv[] ) { if (!c) { plugin_errno = SLURM_AUTH_BADARG; diff --git a/src/plugins/auth/auth_none.c b/src/plugins/auth/auth_none.c index 4c6202b56a375bc51e415a317ef7591ada4441e9..ad42369e7c749560f08d1ead64c31281c9d76c23 100644 --- a/src/plugins/auth/auth_none.c +++ b/src/plugins/auth/auth_none.c @@ -146,9 +146,10 @@ enum { * init() is called when the plugin is loaded, before any other functions * are called. Put global initialization here. */ -void init ( void ) +int init ( void ) { debug("authentication==none"); + return SLURM_SUCCESS; } /* @@ -161,7 +162,7 @@ void init ( void ) * NULL if it cannot allocate a credential. */ slurm_auth_credential_t * -slurm_auth_create( void ) +slurm_auth_create( void *argv[] ) { slurm_auth_credential_t *cred; @@ -194,7 +195,7 @@ slurm_auth_destroy( slurm_auth_credential_t *cred ) * Return SLURM_SUCCESS if the credential is in order and valid. */ int -slurm_auth_verify( slurm_auth_credential_t *cred ) +slurm_auth_verify( slurm_auth_credential_t *cred, void *argv[] ) { return SLURM_SUCCESS; }