4 Copyright (c) 2000 The Regents of the University of Michigan.
7 Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
9 Copyright (c) 2014, Intel Corporation.
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
15 1. Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 3. Neither the name of the University nor the names of its
21 contributors may be used to endorse or promote products derived
22 from this software without specific prior written permission.
24 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <sys/param.h>
54 #include <lnet/nidstr.h>
64 #include <lustre/lustre_idl.h>
66 #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel"
67 #define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.sptlrpc.init/channel"
69 #define TOKEN_BUF_SIZE 8192
81 struct svc_nego_data {
86 char nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
87 gss_buffer_desc in_tok;
88 gss_buffer_desc out_tok;
89 gss_buffer_desc in_handle;
90 gss_buffer_desc out_handle;
97 gss_buffer_desc ctx_token;
101 do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
102 gss_OID mechoid, gss_buffer_desc *context_token)
105 const char *mechname;
108 printerr(2, "doing downcall\n");
109 mechname = gss_OID_mech_name(mechoid);
110 if (mechname == NULL)
112 f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
114 printerr(0, "WARNING: unable to open downcall channel "
116 SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
119 qword_printhex(f, out_handle->value, out_handle->length);
120 /* XXX are types OK for the rest of this? */
121 qword_printint(f, 3600); /* an hour should be sufficient */
122 qword_printint(f, cred->cr_remote);
123 qword_printint(f, cred->cr_usr_root);
124 qword_printint(f, cred->cr_usr_mds);
125 qword_printint(f, cred->cr_usr_oss);
126 qword_printint(f, cred->cr_mapped_uid);
127 qword_printint(f, cred->cr_uid);
128 qword_printint(f, cred->cr_gid);
129 qword_print(f, mechname);
130 qword_printhex(f, context_token->value, context_token->length);
135 printerr(0, "WARNING: downcall failed\n");
139 struct gss_verifier {
141 gss_buffer_desc body;
144 #define RPCSEC_GSS_SEQ_WIN 5
147 send_response(FILE *f, gss_buffer_desc *in_handle, gss_buffer_desc *in_token,
148 u_int32_t maj_stat, u_int32_t min_stat,
149 gss_buffer_desc *out_handle, gss_buffer_desc *out_token)
151 char buf[2 * TOKEN_BUF_SIZE];
153 int blen = sizeof(buf);
157 printerr(2, "sending reply\n");
158 qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
159 qword_addhex(&bp, &blen, in_token->value, in_token->length);
160 qword_addint(&bp, &blen, 3600); /* an hour should be sufficient */
161 qword_adduint(&bp, &blen, maj_stat);
162 qword_adduint(&bp, &blen, min_stat);
163 qword_addhex(&bp, &blen, out_handle->value, out_handle->length);
164 qword_addhex(&bp, &blen, out_token->value, out_token->length);
165 qword_addeol(&bp, &blen);
167 printerr(0, "WARNING: send_response: message too long\n");
170 g = open(SVCGSSD_INIT_CHANNEL, O_WRONLY);
172 printerr(0, "WARNING: open %s failed: %s\n",
173 SVCGSSD_INIT_CHANNEL, strerror(errno));
177 printerr(3, "writing message: %s", buf);
178 if (write(g, buf, bp - buf) == -1) {
179 printerr(0, "WARNING: failed to write message\n");
187 #define rpc_auth_ok 0
188 #define rpc_autherr_badcred 1
189 #define rpc_autherr_rejectedcred 2
190 #define rpc_autherr_badverf 3
191 #define rpc_autherr_rejectedverf 4
192 #define rpc_autherr_tooweak 5
193 #define rpcsec_gsserr_credproblem 13
194 #define rpcsec_gsserr_ctxproblem 14
197 get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
198 lnet_nid_t nid, uint32_t lustre_svc)
200 u_int32_t maj_stat, min_stat;
201 gss_buffer_desc name;
202 char *sname, *host, *realm;
203 const int namebuf_size = 512;
204 char namebuf[namebuf_size];
206 gss_OID name_type = GSS_C_NO_OID;
210 cred->cr_usr_root = cred->cr_usr_mds = cred->cr_usr_oss = 0;
211 cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
213 maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
214 if (maj_stat != GSS_S_COMPLETE) {
215 pgsserr("get_ids: gss_display_name",
216 maj_stat, min_stat, mech);
219 if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
220 !(sname = calloc(name.length + 1, 1))) {
221 printerr(0, "WARNING: get_ids: error allocating %zu bytes "
222 "for sname\n", name.length + 1);
223 gss_release_buffer(&min_stat, &name);
226 memcpy(sname, name.value, name.length);
227 sname[name.length] = '\0';
228 gss_release_buffer(&min_stat, &name);
230 if (lustre_svc == LUSTRE_GSS_SVC_MDS)
231 lookup_mapping(sname, nid, &cred->cr_mapped_uid);
233 cred->cr_mapped_uid = -1;
235 realm = strchr(sname, '@');
239 printerr(0, "ERROR: %s has no realm name\n", sname);
243 host = strchr(sname, '/');
247 if (strcmp(sname, GSSD_SERVICE_MGS) == 0) {
248 printerr(0, "forbid %s as a user name\n", sname);
252 /* 1. check host part */
254 if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
255 printerr(0, "ERROR: failed to resolve hostname for "
256 "%s/%s@%s from %016llx\n",
257 sname, host, realm, nid);
261 if (strcasecmp(host, namebuf)) {
262 printerr(0, "ERROR: %s/%s@%s claimed hostname doesn't "
263 "match %s, nid %016llx\n", sname, host, realm,
268 if (!strcmp(sname, GSSD_SERVICE_MDS) ||
269 !strcmp(sname, GSSD_SERVICE_OSS)) {
270 printerr(0, "ERROR: %s@%s from %016llx doesn't "
271 "bind with hostname\n", sname, realm, nid);
276 /* 2. check realm and user */
277 switch (lustre_svc) {
278 case LUSTRE_GSS_SVC_MDS:
279 if (strcasecmp(mds_local_realm, realm)) {
282 /* only allow mapped user from remote realm */
283 if (cred->cr_mapped_uid == -1) {
284 printerr(0, "ERROR: %s%s%s@%s from %016llx "
285 "is remote but without mapping\n",
286 sname, host ? "/" : "",
287 host ? host : "", realm, nid);
291 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
293 cred->cr_usr_root = 1;
294 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
296 cred->cr_usr_mds = 1;
297 } else if (!strcmp(sname, GSSD_SERVICE_OSS)) {
299 cred->cr_usr_oss = 1;
301 pw = getpwnam(sname);
303 cred->cr_uid = pw->pw_uid;
304 printerr(2, "%s resolve to uid %u\n",
305 sname, cred->cr_uid);
306 } else if (cred->cr_mapped_uid != -1) {
307 printerr(2, "user %s from %016llx is "
308 "mapped to %u\n", sname, nid,
309 cred->cr_mapped_uid);
311 printerr(0, "ERROR: invalid user, "
312 "%s/%s@%s from %016llx\n",
313 sname, host, realm, nid);
321 case LUSTRE_GSS_SVC_MGS:
322 if (!strcmp(sname, GSSD_SERVICE_OSS)) {
324 cred->cr_usr_oss = 1;
327 case LUSTRE_GSS_SVC_OSS:
328 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
330 cred->cr_usr_root = 1;
331 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
333 cred->cr_usr_mds = 1;
335 if (cred->cr_uid == -1) {
336 printerr(0, "ERROR: svc %d doesn't accept user %s "
337 "from %016llx\n", lustre_svc, sname, nid);
348 printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
349 lustre_svc_name[lustre_svc], sname,
350 host ? "/" : "", host ? host : "", realm, nid);
355 typedef struct gss_union_ctx_id_t {
357 gss_ctx_id_t internal_ctx_id;
358 } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
360 int handle_sk(struct svc_nego_data *snd)
362 #ifdef HAVE_OPENSSL_SSK
363 struct sk_cred *skc = NULL;
364 struct svc_cred cred;
365 gss_buffer_desc bufs[SK_INIT_BUFFERS];
366 gss_buffer_desc remote_pub_key = GSS_C_EMPTY_BUFFER;
368 uint32_t rc = GSS_S_DEFECTIVE_TOKEN;
373 printerr(3, "Handling sk request\n");
374 memset(bufs, 0, sizeof(gss_buffer_desc) * SK_INIT_BUFFERS);
376 /* See lgss_sk_using_cred() for client side token formation.
377 * Decoding initiator buffers */
378 i = sk_decode_netstring(bufs, SK_INIT_BUFFERS, &snd->in_tok);
379 if (i < SK_INIT_BUFFERS) {
380 printerr(0, "Invalid netstring token received from peer\n");
381 goto cleanup_buffers;
384 /* Allowing for a larger length first buffer in the future */
385 if (bufs[SK_INIT_VERSION].length < sizeof(version)) {
386 printerr(0, "Invalid version received (wrong size)\n");
387 goto cleanup_buffers;
389 memcpy(&version, bufs[SK_INIT_VERSION].value, sizeof(version));
390 version = be32toh(version);
391 if (version != SK_MSG_VERSION) {
392 printerr(0, "Invalid version received: %d\n", version);
393 goto cleanup_buffers;
398 /* target must be a null terminated string */
399 i = bufs[SK_INIT_TARGET].length - 1;
400 target = bufs[SK_INIT_TARGET].value;
401 if (i >= 0 && target[i] != '\0') {
402 printerr(0, "Invalid target from netstring\n");
403 goto cleanup_buffers;
406 if (bufs[SK_INIT_FLAGS].length != sizeof(flags)) {
407 printerr(0, "Invalid flags from netstring\n");
408 goto cleanup_buffers;
410 memcpy(&flags, bufs[SK_INIT_FLAGS].value, sizeof(flags));
412 skc = sk_create_cred(target, snd->nm_name, be32toh(flags));
414 printerr(0, "Failed to create sk credentials\n");
415 goto cleanup_buffers;
418 /* Verify that the peer has used a prime size greater or equal to
419 * the size specified in the key file which may contain only zero
420 * fill but the size specifies the mimimum supported size on
422 if (skc->sc_flags & LGSS_SVC_PRIV &&
423 bufs[SK_INIT_P].length < skc->sc_p.length) {
424 printerr(0, "Peer DHKE prime does not meet the size required "
425 "by keyfile: %zd bits\n", skc->sc_p.length * 8);
426 goto cleanup_buffers;
429 /* Throw out the p from the server and use the wire data */
430 free(skc->sc_p.value);
431 skc->sc_p.value = NULL;
432 skc->sc_p.length = 0;
434 /* Take control of all the allocated buffers from decoding */
435 if (bufs[SK_INIT_RANDOM].length !=
436 sizeof(skc->sc_kctx.skc_peer_random)) {
437 printerr(0, "Invalid size for client random\n");
438 goto cleanup_buffers;
441 memcpy(&skc->sc_kctx.skc_peer_random, bufs[SK_INIT_RANDOM].value,
442 sizeof(skc->sc_kctx.skc_peer_random));
443 skc->sc_p = bufs[SK_INIT_P];
444 remote_pub_key = bufs[SK_INIT_PUB_KEY];
445 skc->sc_nodemap_hash = bufs[SK_INIT_NODEMAP];
446 skc->sc_hmac = bufs[SK_INIT_HMAC];
448 /* Verify HMAC from peer. Ideally this would happen before anything
449 * else but we don't have enough information to lookup key without the
450 * token (fsname and cluster_hash) so it's done after. */
451 rc = sk_verify_hmac(skc, bufs, SK_INIT_BUFFERS - 1, EVP_sha256(),
453 if (rc != GSS_S_COMPLETE) {
454 printerr(0, "HMAC verification error: 0x%x from peer %s\n",
455 rc, libcfs_nid2str((lnet_nid_t)snd->nid));
456 goto cleanup_partial;
459 /* Check that the cluster hash matches the hash of nodemap name */
460 rc = sk_verify_hash(snd->nm_name, EVP_sha256(), &skc->sc_nodemap_hash);
461 if (rc != GSS_S_COMPLETE) {
462 printerr(0, "Cluster hash failed validation: 0x%x\n", rc);
463 goto cleanup_partial;
466 rc = sk_gen_params(skc);
467 if (rc != GSS_S_COMPLETE) {
468 printerr(0, "Failed to generate DH params for responder\n");
469 goto cleanup_partial;
471 if (sk_compute_dh_key(skc, &remote_pub_key)) {
472 printerr(0, "Failed to compute session key from DH params\n");
473 goto cleanup_partial;
476 /* Cleanup init buffers we have copied or don't need anymore */
477 free(bufs[SK_INIT_VERSION].value);
478 free(bufs[SK_INIT_RANDOM].value);
479 free(bufs[SK_INIT_TARGET].value);
480 free(bufs[SK_INIT_FLAGS].value);
482 /* Server reply contains the servers public key, random, and HMAC */
483 version = htobe32(SK_MSG_VERSION);
484 bufs[SK_RESP_VERSION].value = &version;
485 bufs[SK_RESP_VERSION].length = sizeof(version);
486 bufs[SK_RESP_RANDOM].value = &skc->sc_kctx.skc_host_random;
487 bufs[SK_RESP_RANDOM].length = sizeof(skc->sc_kctx.skc_host_random);
488 bufs[SK_RESP_PUB_KEY] = skc->sc_pub_key;
489 if (sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs,
490 SK_RESP_BUFFERS - 1, EVP_sha256(),
492 printerr(0, "Failed to sign parameters\n");
495 bufs[SK_RESP_HMAC] = skc->sc_hmac;
496 if (sk_encode_netstring(bufs, SK_RESP_BUFFERS, &snd->out_tok)) {
497 printerr(0, "Failed to encode netstring for token\n");
500 printerr(2, "Created netstring of %zd bytes\n", snd->out_tok.length);
502 if (sk_session_kdf(skc, snd->nid, &snd->in_tok, &snd->out_tok)) {
503 printerr(0, "Failed to calulate derviced session key\n");
506 if (sk_compute_keys(skc)) {
507 printerr(0, "Failed to compute HMAC and encryption keys\n");
510 if (sk_serialize_kctx(skc, &snd->ctx_token)) {
511 printerr(0, "Failed to serialize context for kernel\n");
515 snd->out_handle.length = sizeof(snd->handle_seq);
516 memcpy(snd->out_handle.value, &snd->handle_seq,
517 sizeof(snd->handle_seq));
518 snd->maj_stat = GSS_S_COMPLETE;
520 /* fix credentials */
521 memset(&cred, 0, sizeof(cred));
522 cred.cr_mapped_uid = -1;
524 if (skc->sc_flags & LGSS_ROOT_CRED_ROOT)
525 cred.cr_usr_root = 1;
526 if (skc->sc_flags & LGSS_ROOT_CRED_MDT)
528 if (skc->sc_flags & LGSS_ROOT_CRED_OST)
531 do_svc_downcall(&snd->out_handle, &cred, snd->mech, &snd->ctx_token);
533 /* cleanup ctx_token, out_tok is cleaned up in handle_channel_req */
534 free(remote_pub_key.value);
535 free(snd->ctx_token.value);
536 snd->ctx_token.length = 0;
538 printerr(3, "sk returning success\n");
542 for (i = 0; i < SK_INIT_BUFFERS; i++)
549 free(bufs[SK_INIT_VERSION].value);
550 free(bufs[SK_INIT_RANDOM].value);
551 free(bufs[SK_INIT_TARGET].value);
552 free(bufs[SK_INIT_FLAGS].value);
553 free(remote_pub_key.value);
560 if (snd->ctx_token.value) {
561 free(snd->ctx_token.value);
562 snd->ctx_token.value = 0;
563 snd->ctx_token.length = 0;
565 free(remote_pub_key.value);
567 printerr(3, "sk returning failure\n");
568 #else /* !HAVE_OPENSSL_SSK */
569 printerr(0, "ERROR: shared key subflavour is not enabled\n");
570 #endif /* HAVE_OPENSSL_SSK */
574 int handle_null(struct svc_nego_data *snd)
576 struct svc_cred cred;
580 /* null just uses the same token as the return token and for
581 * for sending to the kernel. It is a single uint64_t. */
582 if (snd->in_tok.length != sizeof(uint64_t)) {
583 snd->maj_stat = GSS_S_DEFECTIVE_TOKEN;
584 printerr(0, "Invalid token size (%zd) received\n",
588 snd->out_tok.length = snd->in_tok.length;
589 snd->out_tok.value = malloc(snd->out_tok.length);
590 if (!snd->out_tok.value) {
591 snd->maj_stat = GSS_S_FAILURE;
592 printerr(0, "Failed to allocate out_tok\n");
596 snd->ctx_token.length = snd->in_tok.length;
597 snd->ctx_token.value = malloc(snd->ctx_token.length);
598 if (!snd->ctx_token.value) {
599 snd->maj_stat = GSS_S_FAILURE;
600 printerr(0, "Failed to allocate ctx_token\n");
604 snd->out_handle.length = sizeof(snd->handle_seq);
605 memcpy(snd->out_handle.value, &snd->handle_seq,
606 sizeof(snd->handle_seq));
607 snd->maj_stat = GSS_S_COMPLETE;
609 memcpy(&tmp, snd->in_tok.value, sizeof(tmp));
611 flags = (uint32_t)(tmp & 0x00000000ffffffff);
612 memset(&cred, 0, sizeof(cred));
613 cred.cr_mapped_uid = -1;
615 if (flags & LGSS_ROOT_CRED_ROOT)
616 cred.cr_usr_root = 1;
617 if (flags & LGSS_ROOT_CRED_MDT)
619 if (flags & LGSS_ROOT_CRED_OST)
622 do_svc_downcall(&snd->out_handle, &cred, snd->mech, &snd->ctx_token);
624 /* cleanup ctx_token, out_tok is cleaned up in handle_channel_req */
625 free(snd->ctx_token.value);
626 snd->ctx_token.length = 0;
631 static int handle_krb(struct svc_nego_data *snd)
634 gss_name_t client_name;
635 gss_buffer_desc ignore_out_tok = {.value = NULL};
636 gss_OID mech = GSS_C_NO_OID;
637 gss_cred_id_t svc_cred;
638 u_int32_t ignore_min_stat;
639 struct svc_cred cred;
641 svc_cred = gssd_select_svc_cred(snd->lustre_svc);
643 printerr(0, "no service credential for svc %u\n",
648 snd->maj_stat = gss_accept_sec_context(&snd->min_stat, &snd->ctx,
649 svc_cred, &snd->in_tok,
650 GSS_C_NO_CHANNEL_BINDINGS,
652 &snd->out_tok, &ret_flags, NULL,
655 if (snd->maj_stat == GSS_S_CONTINUE_NEEDED) {
656 printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n");
658 /* Save the context handle for future calls */
659 snd->out_handle.length = sizeof(snd->ctx);
660 memcpy(snd->out_handle.value, &snd->ctx, sizeof(snd->ctx));
662 } else if (snd->maj_stat != GSS_S_COMPLETE) {
663 printerr(0, "WARNING: gss_accept_sec_context failed\n");
664 pgsserr("handle_krb: gss_accept_sec_context",
665 snd->maj_stat, snd->min_stat, mech);
669 if (get_ids(client_name, mech, &cred, snd->nid, snd->lustre_svc)) {
670 /* get_ids() prints error msg */
671 snd->maj_stat = GSS_S_BAD_NAME; /* XXX ? */
672 gss_release_name(&ignore_min_stat, &client_name);
675 gss_release_name(&ignore_min_stat, &client_name);
677 /* Context complete. Pass handle_seq in out_handle to use
678 * for context lookup in the kernel. */
679 snd->out_handle.length = sizeof(snd->handle_seq);
680 memcpy(snd->out_handle.value, &snd->handle_seq,
681 sizeof(snd->handle_seq));
683 /* kernel needs ctx to calculate verifier on null response, so
684 * must give it context before doing null call: */
685 if (serialize_context_for_kernel(snd->ctx, &snd->ctx_token, mech)) {
686 printerr(0, "WARNING: handle_krb: "
687 "serialize_context_for_kernel failed\n");
688 snd->maj_stat = GSS_S_FAILURE;
691 /* We no longer need the gss context */
692 gss_delete_sec_context(&ignore_min_stat, &snd->ctx, &ignore_out_tok);
693 do_svc_downcall(&snd->out_handle, &cred, mech, &snd->ctx_token);
698 if (snd->ctx != GSS_C_NO_CONTEXT)
699 gss_delete_sec_context(&ignore_min_stat, &snd->ctx,
706 * return -1 only if we detect error during reading from upcall channel,
707 * all other cases return 0.
709 int handle_channel_request(FILE *f)
711 char in_tok_buf[TOKEN_BUF_SIZE];
712 char in_handle_buf[15];
713 char out_handle_buf[15];
714 gss_buffer_desc ctx_token = {.value = NULL},
715 null_token = {.value = NULL};
716 uint32_t lustre_mech;
722 u_int32_t ignore_min_stat;
723 struct svc_nego_data snd = {
724 .in_tok.value = in_tok_buf,
725 .in_handle.value = in_handle_buf,
726 .out_handle.value = out_handle_buf,
727 .maj_stat = GSS_S_FAILURE,
728 .ctx = GSS_C_NO_CONTEXT,
731 printerr(2, "handling request\n");
732 if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
733 printerr(0, "WARNING: failed reading request\n");
739 /* see rsi_request() for the format of data being input here */
740 qword_get(&cp, (char *)&snd.lustre_svc, sizeof(snd.lustre_svc));
742 /* lustre_svc is the svc and gss subflavor */
743 lustre_mech = (snd.lustre_svc & LUSTRE_GSS_MECH_MASK) >>
744 LUSTRE_GSS_MECH_SHIFT;
745 snd.lustre_svc = snd.lustre_svc & LUSTRE_GSS_SVC_MASK;
746 switch (lustre_mech) {
749 printerr(1, "WARNING: Request for kerberos but service "
750 "support not enabled\n");
757 printerr(1, "WARNING: Request for gssnull but service "
758 "support not enabled\n");
764 #ifdef HAVE_OPENSSL_SSK
766 printerr(1, "WARNING: Request for sk but service "
767 "support not enabled\n");
772 printerr(1, "ERROR: Request for sk but service "
773 "support not enabled\n");
777 printerr(0, "WARNING: invalid mechanism recevied: %d\n",
783 qword_get(&cp, (char *)&snd.nid, sizeof(snd.nid));
784 qword_get(&cp, (char *)&snd.handle_seq, sizeof(snd.handle_seq));
785 qword_get(&cp, snd.nm_name, sizeof(snd.nm_name));
786 printerr(2, "handling req: svc %u, nid %016llx, idx %"PRIx64" nodemap "
787 "%s\n", snd.lustre_svc, snd.nid, snd.handle_seq, snd.nm_name);
789 get_len = qword_get(&cp, snd.in_handle.value, sizeof(in_handle_buf));
791 printerr(0, "WARNING: failed parsing request\n");
794 snd.in_handle.length = (size_t)get_len;
796 printerr(3, "in_handle:\n");
797 print_hexl(3, snd.in_handle.value, snd.in_handle.length);
799 get_len = qword_get(&cp, snd.in_tok.value, sizeof(in_tok_buf));
801 printerr(0, "WARNING: failed parsing request\n");
804 snd.in_tok.length = (size_t)get_len;
806 printerr(3, "in_tok:\n");
807 print_hexl(3, snd.in_tok.value, snd.in_tok.length);
809 if (snd.in_handle.length != 0) { /* CONTINUE_INIT case */
810 if (snd.in_handle.length != sizeof(snd.ctx)) {
811 printerr(0, "WARNING: input handle has unexpected "
812 "length %zu\n", snd.in_handle.length);
815 /* in_handle is the context id stored in the out_handle
816 * for the GSS_S_CONTINUE_NEEDED case below. */
817 memcpy(&snd.ctx, snd.in_handle.value, snd.in_handle.length);
820 if (lustre_mech == LGSS_MECH_KRB5)
821 rc = handle_krb(&snd);
822 else if (lustre_mech == LGSS_MECH_SK)
823 rc = handle_sk(&snd);
824 else if (lustre_mech == LGSS_MECH_NULL)
825 rc = handle_null(&snd);
827 printerr(0, "WARNING: Received or request for"
828 "subflavor that is not enabled: %d\n", lustre_mech);
831 /* Failures send a null token */
833 send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
834 snd.min_stat, &snd.out_handle, &snd.out_tok);
836 send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
837 snd.min_stat, &null_token, &null_token);
839 /* cleanup buffers */
840 if (snd.ctx_token.value != NULL)
841 free(ctx_token.value);
842 if (snd.out_tok.value != NULL)
843 gss_release_buffer(&ignore_min_stat, &snd.out_tok);
845 /* For junk wire data just ignore */