/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2020 Intel, Inc. All rights reserved. * * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2019 Mellanox Technologies, Inc. All rights reserved. * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ /** * @file * * This interface is for psecurity support. PMIx doesn't need much in * this regard, but we do need a mechanism for authenticating connections. * * Only *one* plugin will be active in a client, but multiple plugins may * be active in a server. Thus, this is a multi-select framework. * * Available plugins may be defined at runtime via the typical MCA parameter * syntax. */ #ifndef PMIX_PSEC_H #define PMIX_PSEC_H #include "src/include/pmix_config.h" #include "src/mca/base/pmix_mca_base_framework.h" #include "src/mca/base/pmix_mca_base_var.h" #include "src/mca/mca.h" #include "src/mca/ptl/ptl_types.h" BEGIN_C_DECLS /* forward declaration */ struct pmix_peer_t; /****** MODULE DEFINITION ******/ /** * Initialize the module. Returns an error if the module cannot * run, success if it can and wants to be used. */ typedef pmix_status_t (*pmix_psec_base_module_init_fn_t)(void); /** * Finalize the module. Tear down any allocated storage, disconnect * from any system support (e.g., LDAP server) */ typedef void (*pmix_psec_base_module_fini_fn_t)(void); /**** CLIENT-SIDE FUNCTIONS ****/ /** * Create and return a credential for this client - this * could be a string or a byte array, which is why we must * also return the length. The directives contain info on * desired credential type, or other directives used by * the credential agent. The returned info array typically * contains the name of the agent issuing the credential, * plus any other info the agent chooses to return. */ typedef pmix_status_t (*pmix_psec_base_module_create_cred_fn_t)(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, pmix_byte_object_t *cred); /** * Perform the client-side handshake. Note that it is not required * (and indeed, would be rare) for a protocol to use both the * credential and handshake interfaces. It is acceptable, therefore, * for one of them to be NULL */ typedef pmix_status_t (*pmix_psec_base_module_client_hndshk_fn_t)(int sd); /**** SERVER-SIDE FUNCTIONS ****/ /** * Validate a client's credential - the credential could be a string * or an array of bytes, which is why we include the length. The directives * contain information provided by the requestor to aid in the validation * process - e.g., the uid/gid of the process seeking validation, or * the name of the agent being asked to perform the validation. The * returned info array typically contains the name of the agent that * actually performed the validation, plus any other info the agent * chooses to return (e.g., the uid/gid contained in the credential) */ typedef pmix_status_t (*pmix_psec_base_module_validate_cred_fn_t)(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, const pmix_byte_object_t *cred); /** * Perform the server-side handshake. Note that it is not required * (and indeed, would be rare) for a protocol to use both the * credential and handshake interfaces. It is acceptable, therefore, * for one of them to be NULL */ typedef pmix_status_t (*pmix_psec_base_module_server_hndshk_fn_t)(int sd); /** * Base structure for a PSEC module */ typedef struct { char *name; /* init/finalize */ pmix_psec_base_module_init_fn_t init; pmix_psec_base_module_fini_fn_t finalize; /** Client-side */ pmix_psec_base_module_create_cred_fn_t create_cred; pmix_psec_base_module_client_hndshk_fn_t client_handshake; /** Server-side */ pmix_psec_base_module_validate_cred_fn_t validate_cred; pmix_psec_base_module_server_hndshk_fn_t server_handshake; } pmix_psec_module_t; /* define an API module */ /* get a list of available options - caller must free results * when done */ PMIX_EXPORT char *pmix_psec_base_get_available_modules(void); /* Select a psec module for a given peer */ PMIX_EXPORT pmix_psec_module_t *pmix_psec_base_assign_module(const char *options); /* MACROS FOR EXECUTING PSEC FUNCTIONS */ #define PMIX_PSEC_CREATE_CRED(r, p, d, nd, in, nin, c) \ (r) = (p)->nptr->compat.psec->create_cred((struct pmix_peer_t *) (p), (d), (nd), (in), (nin), c) #define PMIX_PSEC_CLIENT_HANDSHAKE(r, p, sd) (r) = (p)->nptr->compat.psec->client_handshake(sd) #define PMIX_PSEC_VALIDATE_CRED(r, p, d, nd, in, nin, c) \ (r) = (p)->nptr->compat.psec->validate_cred((struct pmix_peer_t *) (p), (d), (nd), (in), \ (nin), c) #define PMIX_PSEC_VALIDATE_CONNECTION(r, p, d, nd, in, nin, c) \ do { \ int _r; \ /* if a credential is available, then check it */ \ if (NULL != (p)->nptr->compat.psec->validate_cred) { \ _r = (p)->nptr->compat.psec->validate_cred((struct pmix_peer_t *) (p), (d), (nd), \ (in), (nin), c); \ if (PMIX_SUCCESS != _r) { \ pmix_output_verbose(2, pmix_globals.debug_output, \ "validation of credential failed: %s", PMIx_Error_string(_r)); \ } else { \ pmix_output_verbose(2, pmix_globals.debug_output, "credential validated"); \ } \ (r) = _r; \ } else if (NULL != (p)->nptr->compat.psec->server_handshake) { \ /* request the handshake if the security mode calls for it */ \ pmix_output_verbose(2, pmix_globals.debug_output, "requesting handshake"); \ _r = PMIX_ERR_READY_FOR_HANDSHAKE; \ (r) = _r; \ } else { \ /* this is not allowed */ \ (r) = PMIX_ERR_NOT_SUPPORTED; \ } \ } while (0) #define PMIX_PSEC_SERVER_HANDSHAKE_IFNEED(r, p, d, nd, in, nin, c) \ if (PMIX_ERR_READY_FOR_HANDSHAKE == r) { \ int _r; \ /* execute the handshake if the security mode calls for it */ \ pmix_output_verbose(2, pmix_globals.debug_output, "executing handshake"); \ if (PMIX_SUCCESS != (_r = p->nptr->compat.psec->server_handshake((p)->sd))) { \ PMIX_ERROR_LOG(_r); \ } \ /* Update the reply status */ \ (r) = _r; \ } /**** COMPONENT STRUCTURE DEFINITION ****/ /* define a component-level API for initializing the component */ typedef pmix_status_t (*pmix_psec_base_component_init_fn_t)(void); /* define a component-level API for finalizing the component */ typedef void (*pmix_psec_base_component_finalize_fn_t)(void); /* define a component-level API for getting a module */ typedef pmix_psec_module_t *(*pmix_psec_base_component_assign_module_fn_t)(void); /* * the standard component data structure */ struct pmix_psec_base_component_t { pmix_mca_base_component_t base; int priority; pmix_psec_base_component_init_fn_t init; pmix_psec_base_component_finalize_fn_t finalize; pmix_psec_base_component_assign_module_fn_t assign_module; }; typedef struct pmix_psec_base_component_t pmix_psec_base_component_t; /* * Macro for use in components that are of type psec */ #define PMIX_PSEC_BASE_VERSION_1_0_0 PMIX_MCA_BASE_VERSION_1_0_0("psec", 1, 0, 0) END_C_DECLS #endif