This source file includes following definitions.
- native_init
- native_finalize
- create_cred
- validate_cred
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <src/include/pmix_config.h>
14
15 #include <unistd.h>
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19
20 #include <pmix_common.h>
21
22 #include "src/include/pmix_socket_errno.h"
23 #include "src/include/pmix_globals.h"
24 #include "src/util/argv.h"
25 #include "src/util/error.h"
26 #include "src/util/output.h"
27
28 #include "src/mca/psec/base/base.h"
29 #include "psec_native.h"
30
31 static pmix_status_t native_init(void);
32 static void native_finalize(void);
33 static pmix_status_t create_cred(struct pmix_peer_t *peer,
34 const pmix_info_t directives[], size_t ndirs,
35 pmix_info_t **info, size_t *ninfo,
36 pmix_byte_object_t *cred);
37 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
38 const pmix_info_t directives[], size_t ndirs,
39 pmix_info_t **info, size_t *ninfo,
40 const pmix_byte_object_t *cred);
41
42 pmix_psec_module_t pmix_native_module = {
43 .name = "native",
44 .init = native_init,
45 .finalize = native_finalize,
46 .create_cred = create_cred,
47 .validate_cred = validate_cred
48 };
49
50 static pmix_status_t native_init(void)
51 {
52 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
53 "psec: native init");
54 return PMIX_SUCCESS;
55 }
56
57 static void native_finalize(void)
58 {
59 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
60 "psec: native finalize");
61 }
62
63 static pmix_status_t create_cred(struct pmix_peer_t *peer,
64 const pmix_info_t directives[], size_t ndirs,
65 pmix_info_t **info, size_t *ninfo,
66 pmix_byte_object_t *cred)
67 {
68 pmix_peer_t *pr = (pmix_peer_t*)peer;
69 char **types;
70 size_t n, m;
71 bool takeus;
72 uid_t euid;
73 gid_t egid;
74 char *tmp, *ptr;
75
76
77 PMIX_BYTE_OBJECT_CONSTRUCT(cred);
78
79
80
81 if (NULL != directives && 0 < ndirs) {
82
83
84 takeus = true;
85 for (n=0; n < ndirs; n++) {
86 if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
87
88 types = pmix_argv_split(directives[n].value.data.string, ',');
89
90 takeus = false;
91 for (m=0; NULL != types[m]; m++) {
92 if (0 == strcmp(types[m], "native")) {
93
94 takeus = true;
95 break;
96 }
97 }
98 pmix_argv_free(types);
99 break;
100 }
101 }
102 if (!takeus) {
103 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
104 return PMIX_ERR_NOT_SUPPORTED;
105 }
106 }
107
108 if (PMIX_PROTOCOL_V1 == pr->protocol) {
109
110 goto complete;
111 } else if (PMIX_PROTOCOL_V2 == pr->protocol) {
112
113
114 tmp = (char*)malloc(sizeof(uid_t) + sizeof(gid_t));
115 if (NULL == tmp) {
116 return PMIX_ERR_NOMEM;
117 }
118 euid = geteuid();
119 memcpy(tmp, &euid, sizeof(uid_t));
120 ptr = tmp + sizeof(uid_t);
121 egid = getegid();
122 memcpy(ptr, &egid, sizeof(gid_t));
123 cred->bytes = tmp;
124 cred->size = sizeof(uid_t) + sizeof(gid_t);
125 goto complete;
126 } else {
127
128 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
129 return PMIX_ERR_NOT_SUPPORTED;
130 }
131
132 complete:
133 if (NULL != info) {
134
135 PMIX_INFO_CREATE(*info, 1);
136 if (NULL == *info) {
137 return PMIX_ERR_NOMEM;
138 }
139 *ninfo = 1;
140 PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "native", PMIX_STRING);
141 }
142 return PMIX_SUCCESS;
143 }
144
145 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
146 const pmix_info_t directives[], size_t ndirs,
147 pmix_info_t **info, size_t *ninfo,
148 const pmix_byte_object_t *cred)
149 {
150 pmix_peer_t *pr = (pmix_peer_t*)peer;
151
152 #if defined(SO_PEERCRED)
153 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
154 #define HAVE_STRUCT_UCRED_UID
155 struct sockpeercred ucred;
156 #else
157 struct ucred ucred;
158 #endif
159 socklen_t crlen = sizeof (ucred);
160 #endif
161 uid_t euid = -1;
162 gid_t egid = -1;
163 char *ptr;
164 size_t ln;
165 bool takeus;
166 char **types;
167 size_t n, m;
168 uint32_t u32;
169
170 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
171 "psec: native validate_cred %s",
172 (NULL == cred) ? "NULL" : "NON-NULL");
173
174 if (PMIX_PROTOCOL_V1 == pr->protocol) {
175
176 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
177
178 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
179 "psec:native checking getsockopt on socket %d for peer credentials", pr->sd);
180 if (getsockopt(pr->sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) {
181 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
182 "psec: getsockopt SO_PEERCRED failed: %s",
183 strerror (pmix_socket_errno));
184 return PMIX_ERR_INVALID_CRED;
185 }
186 #if defined(HAVE_STRUCT_UCRED_UID)
187 euid = ucred.uid;
188 egid = ucred.gid;
189 #else
190 euid = ucred.cr_uid;
191 egid = ucred.cr_gid;
192 #endif
193
194 #elif defined(HAVE_GETPEEREID)
195 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
196 "psec:native checking getpeereid on socket %d for peer credentials", pr->sd);
197 if (0 != getpeereid(pr->sd, &euid, &egid)) {
198 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
199 "psec: getsockopt getpeereid failed: %s",
200 strerror (pmix_socket_errno));
201 return PMIX_ERR_INVALID_CRED;
202 }
203 #else
204 return PMIX_ERR_NOT_SUPPORTED;
205 #endif
206 } else if (PMIX_PROTOCOL_V2 == pr->protocol) {
207
208
209 if (NULL == cred) {
210
211 return PMIX_ERR_INVALID_CRED;
212 }
213 ln = cred->size;
214 euid = 0;
215 egid = 0;
216 if (sizeof(uid_t) <= ln) {
217 memcpy(&euid, cred->bytes, sizeof(uid_t));
218 ln -= sizeof(uid_t);
219 ptr = cred->bytes + sizeof(uid_t);
220 } else {
221 return PMIX_ERR_INVALID_CRED;
222 }
223 if (sizeof(gid_t) <= ln) {
224 memcpy(&egid, ptr, sizeof(gid_t));
225 } else {
226 return PMIX_ERR_INVALID_CRED;
227 }
228 } else if (PMIX_PROTOCOL_UNDEF != pr->protocol) {
229
230 return PMIX_ERR_NOT_SUPPORTED;
231 }
232
233
234
235 if (NULL != directives && 0 < ndirs) {
236 for (n=0; n < ndirs; n++) {
237 if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
238
239 types = pmix_argv_split(directives[n].value.data.string, ',');
240 takeus = false;
241 for (m=0; NULL != types[m]; m++) {
242 if (0 == strcmp(types[m], "native")) {
243
244 takeus = true;
245 break;
246 }
247 }
248 pmix_argv_free(types);
249 if (!takeus) {
250 return PMIX_ERR_NOT_SUPPORTED;
251 }
252 }
253 }
254 }
255
256
257 if (euid != pr->info->uid) {
258 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
259 "psec: socket cred contains invalid uid %u", euid);
260 return PMIX_ERR_INVALID_CRED;
261 }
262
263
264 if (egid != pr->info->gid) {
265 pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
266 "psec: socket cred contains invalid gid %u", egid);
267 return PMIX_ERR_INVALID_CRED;
268 }
269
270
271 if (NULL != info) {
272 PMIX_INFO_CREATE(*info, 3);
273 if (NULL == *info) {
274 return PMIX_ERR_NOMEM;
275 }
276 *ninfo = 3;
277
278 PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING);
279
280 u32 = euid;
281 PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32);
282
283 u32 = egid;
284 PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32);
285 }
286 return PMIX_SUCCESS;
287
288 }