1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved.
4 * Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
5 *
6 * Copyright (c) 2015 Research Organization for Information Science
7 * and Technology (RIST). All rights reserved.
8 * $COPYRIGHT$
9 *
10 * Additional copyrights may follow
11 *
12 * $HEADER$
13 */
14
15 /**
16 * @file
17 *
18 * This interface is for psecurity support. PMIx doesn't need much in
19 * this regard, but we do need a mechanism for authenticating connections.
20 *
21 * Only *one* plugin will be active in a client, but multiple plugins may
22 * be active in a server. Thus, this is a multi-select framework.
23 *
24 * Available plugins may be defined at runtime via the typical MCA parameter
25 * syntax.
26 */
27
28 #ifndef PMIX_PSEC_H
29 #define PMIX_PSEC_H
30
31 #include <src/include/pmix_config.h>
32
33 #include "src/mca/mca.h"
34 #include "src/mca/base/pmix_mca_base_var.h"
35 #include "src/mca/base/pmix_mca_base_framework.h"
36 #include "src/mca/ptl/ptl_types.h"
37
38 BEGIN_C_DECLS
39
40 /* forward declaration */
41 struct pmix_peer_t;
42
43 /****** MODULE DEFINITION ******/
44
45 /**
46 * Initialize the module. Returns an error if the module cannot
47 * run, success if it can and wants to be used.
48 */
49 typedef pmix_status_t (*pmix_psec_base_module_init_fn_t)(void);
50
51 /**
52 * Finalize the module. Tear down any allocated storage, disconnect
53 * from any system support (e.g., LDAP server)
54 */
55 typedef void (*pmix_psec_base_module_fini_fn_t)(void);
56
57 /**** CLIENT-SIDE FUNCTIONS ****/
58 /**
59 * Create and return a credential for this client - this
60 * could be a string or a byte array, which is why we must
61 * also return the length. The directives contain info on
62 * desired credential type, or other directives used by
63 * the credential agent. The returned info array typically
64 * contains the name of the agent issuing the credential,
65 * plus any other info the agent chooses to return.
66 */
67 typedef pmix_status_t (*pmix_psec_base_module_create_cred_fn_t)(struct pmix_peer_t *peer,
68 const pmix_info_t directives[], size_t ndirs,
69 pmix_info_t **info, size_t *ninfo,
70 pmix_byte_object_t *cred);
71
72 /**
73 * Perform the client-side handshake. Note that it is not required
74 * (and indeed, would be rare) for a protocol to use both the
75 * credential and handshake interfaces. It is acceptable, therefore,
76 * for one of them to be NULL */
77 typedef pmix_status_t (*pmix_psec_base_module_client_hndshk_fn_t)(int sd);
78
79
80 /**** SERVER-SIDE FUNCTIONS ****/
81 /**
82 * Validate a client's credential - the credential could be a string
83 * or an array of bytes, which is why we include the length. The directives
84 * contain information provided by the requestor to aid in the validation
85 * process - e.g., the uid/gid of the process seeking validation, or
86 * the name of the agent being asked to perform the validation. The
87 * returned info array typically contains the name of the agent that
88 * actually performed the validation, plus any other info the agent
89 * chooses to return (e.g., the uid/gid contained in the credential)
90 */
91 typedef pmix_status_t (*pmix_psec_base_module_validate_cred_fn_t)(struct pmix_peer_t *peer,
92 const pmix_info_t directives[], size_t ndirs,
93 pmix_info_t **info, size_t *ninfo,
94 const pmix_byte_object_t *cred);
95
96 /**
97 * Perform the server-side handshake. Note that it is not required
98 * (and indeed, would be rare) for a protocol to use both the
99 * credential and handshake interfaces. It is acceptable, therefore,
100 * for one of them to be NULL */
101 typedef pmix_status_t (*pmix_psec_base_module_server_hndshk_fn_t)(int sd);
102
103 /**
104 * Base structure for a PSEC module
105 */
106 typedef struct {
107 char *name;
108 /* init/finalize */
109 pmix_psec_base_module_init_fn_t init;
110 pmix_psec_base_module_fini_fn_t finalize;
111 /** Client-side */
112 pmix_psec_base_module_create_cred_fn_t create_cred;
113 pmix_psec_base_module_client_hndshk_fn_t client_handshake;
114 /** Server-side */
115 pmix_psec_base_module_validate_cred_fn_t validate_cred;
116 pmix_psec_base_module_server_hndshk_fn_t server_handshake;
117 } pmix_psec_module_t;
118
119
120 /* define an API module */
121
122 /* get a list of available options - caller must free results
123 * when done */
124 PMIX_EXPORT char* pmix_psec_base_get_available_modules(void);
125
126 /* Select a psec module for a given peer */
127 PMIX_EXPORT pmix_psec_module_t* pmix_psec_base_assign_module(const char *options);
128
129 /* MACROS FOR EXECUTING PSEC FUNCTIONS */
130
131 #define PMIX_PSEC_CREATE_CRED(r, p, d, nd, in, nin, c) \
132 (r) = (p)->nptr->compat.psec->create_cred((struct pmix_peer_t*)(p), \
133 (d), (nd), (in), (nin), c)
134
135 #define PMIX_PSEC_CLIENT_HANDSHAKE(r, p, sd) \
136 (r) = (p)->nptr->compat.psec->client_handshake(sd)
137
138 #define PMIX_PSEC_VALIDATE_CRED(r, p, d, nd, in, nin, c) \
139 (r) = (p)->nptr->compat.psec->validate_cred((struct pmix_peer_t*)(p), \
140 (d), (nd), \
141 (in), (nin), c)
142
143 #define PMIX_PSEC_VALIDATE_CONNECTION(r, p, d, nd, in, nin, c) \
144 do { \
145 int _r; \
146 /* if a credential is available, then check it */ \
147 if (NULL != (p)->nptr->compat.psec->validate_cred) { \
148 _r = (p)->nptr->compat.psec->validate_cred((struct pmix_peer_t*)(p), \
149 (d), (nd), (in), (nin), c); \
150 if (PMIX_SUCCESS != _r) { \
151 pmix_output_verbose(2, pmix_globals.debug_output, \
152 "validation of credential failed: %s", \
153 PMIx_Error_string(_r)); \
154 } else { \
155 pmix_output_verbose(2, pmix_globals.debug_output, \
156 "credential validated"); \
157 } \
158 /* send them the result */ \
159 if (PMIX_SUCCESS != (_r = pmix_ptl_base_send_blocking((p)->sd, (char*)&(_r), sizeof(int)))) { \
160 PMIX_ERROR_LOG(_r); \
161 } \
162 (r) = _r; \
163 } else if (NULL != (p)->nptr->compat.psec->server_handshake) { \
164 /* execute the handshake if the security mode calls for it */ \
165 pmix_output_verbose(2, pmix_globals.debug_output, \
166 "executing handshake"); \
167 _r = PMIX_ERR_READY_FOR_HANDSHAKE; \
168 if (PMIX_SUCCESS != (_r = pmix_ptl_base_send_blocking((p)->sd, (char*)&(_r), sizeof(int)))) { \
169 PMIX_ERROR_LOG(_r); \
170 } else { \
171 if (PMIX_SUCCESS != (_r = p->nptr->compat.psec->server_handshake((p)->sd))) { \
172 PMIX_ERROR_LOG(_r); \
173 } \
174 } \
175 (r) = _r; \
176 } else { \
177 /* this is not allowed */ \
178 (r) = PMIX_ERR_NOT_SUPPORTED; \
179 } \
180 } while(0)
181
182 /**** COMPONENT STRUCTURE DEFINITION ****/
183
184 /* define a component-level API for initializing the component */
185 typedef pmix_status_t (*pmix_psec_base_component_init_fn_t)(void);
186
187 /* define a component-level API for finalizing the component */
188 typedef void (*pmix_psec_base_component_finalize_fn_t)(void);
189
190 /* define a component-level API for getting a module */
191 typedef pmix_psec_module_t* (*pmix_psec_base_component_assign_module_fn_t)(void);
192
193 /*
194 * the standard component data structure
195 */
196 struct pmix_psec_base_component_t {
197 pmix_mca_base_component_t base;
198 pmix_mca_base_component_data_t data;
199 int priority;
200 pmix_psec_base_component_init_fn_t init;
201 pmix_psec_base_component_finalize_fn_t finalize;
202 pmix_psec_base_component_assign_module_fn_t assign_module;
203 };
204 typedef struct pmix_psec_base_component_t pmix_psec_base_component_t;
205
206 /*
207 * Macro for use in components that are of type psec
208 */
209 #define PMIX_PSEC_BASE_VERSION_1_0_0 \
210 PMIX_MCA_BASE_VERSION_1_0_0("psec", 1, 0, 0)
211
212 END_C_DECLS
213
214 #endif