4 * Copyright (c) 2000 The Regents of the University of Michigan.
7 * Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
60 #include <lustre/lustre_idl.h>
62 #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel"
63 #define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.sptlrpc.init/channel"
65 #define TOKEN_BUF_SIZE 8192
77 struct svc_nego_data {
82 char nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
83 gss_buffer_desc in_tok;
84 gss_buffer_desc out_tok;
85 gss_buffer_desc in_handle;
86 gss_buffer_desc out_handle;
93 gss_buffer_desc ctx_token;
97 do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
98 gss_OID mechoid, gss_buffer_desc *context_token)
101 const char *mechname;
104 printerr(2, "doing downcall\n");
105 mechname = gss_OID_mech_name(mechoid);
106 if (mechname == NULL)
108 f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
110 printerr(0, "WARNING: unable to open downcall channel "
112 SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
115 qword_printhex(f, out_handle->value, out_handle->length);
116 /* XXX are types OK for the rest of this? */
117 qword_printint(f, 3600); /* an hour should be sufficient */
118 qword_printint(f, cred->cr_remote);
119 qword_printint(f, cred->cr_usr_root);
120 qword_printint(f, cred->cr_usr_mds);
121 qword_printint(f, cred->cr_usr_oss);
122 qword_printint(f, cred->cr_mapped_uid);
123 qword_printint(f, cred->cr_uid);
124 qword_printint(f, cred->cr_gid);
125 qword_print(f, mechname);
126 qword_printhex(f, context_token->value, context_token->length);
131 printerr(0, "WARNING: downcall failed\n");
135 struct gss_verifier {
137 gss_buffer_desc body;
140 #define RPCSEC_GSS_SEQ_WIN 5
143 send_response(FILE *f, gss_buffer_desc *in_handle, gss_buffer_desc *in_token,
144 u_int32_t maj_stat, u_int32_t min_stat,
145 gss_buffer_desc *out_handle, gss_buffer_desc *out_token)
147 char buf[2 * TOKEN_BUF_SIZE];
149 int blen = sizeof(buf);
153 printerr(2, "sending reply\n");
154 qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
155 qword_addhex(&bp, &blen, in_token->value, in_token->length);
156 qword_addint(&bp, &blen, 3600); /* an hour should be sufficient */
157 qword_adduint(&bp, &blen, maj_stat);
158 qword_adduint(&bp, &blen, min_stat);
159 qword_addhex(&bp, &blen, out_handle->value, out_handle->length);
160 qword_addhex(&bp, &blen, out_token->value, out_token->length);
161 qword_addeol(&bp, &blen);
163 printerr(0, "WARNING: send_response: message too long\n");
166 g = open(SVCGSSD_INIT_CHANNEL, O_WRONLY);
168 printerr(0, "WARNING: open %s failed: %s\n",
169 SVCGSSD_INIT_CHANNEL, strerror(errno));
173 printerr(3, "writing message: %s", buf);
174 if (write(g, buf, bp - buf) == -1) {
175 printerr(0, "WARNING: failed to write message\n");
183 #define rpc_auth_ok 0
184 #define rpc_autherr_badcred 1
185 #define rpc_autherr_rejectedcred 2
186 #define rpc_autherr_badverf 3
187 #define rpc_autherr_rejectedverf 4
188 #define rpc_autherr_tooweak 5
189 #define rpcsec_gsserr_credproblem 13
190 #define rpcsec_gsserr_ctxproblem 14
193 get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
194 lnet_nid_t nid, uint32_t lustre_svc)
196 u_int32_t maj_stat, min_stat;
197 gss_buffer_desc name;
198 char *sname, *host, *realm;
199 const int namebuf_size = 512;
200 char namebuf[namebuf_size];
202 gss_OID name_type = GSS_C_NO_OID;
206 cred->cr_usr_root = cred->cr_usr_mds = cred->cr_usr_oss = 0;
207 cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
209 maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
210 if (maj_stat != GSS_S_COMPLETE) {
211 pgsserr("get_ids: gss_display_name",
212 maj_stat, min_stat, mech);
215 if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
216 !(sname = calloc(name.length + 1, 1))) {
217 printerr(0, "WARNING: get_ids: error allocating %zu bytes "
218 "for sname\n", name.length + 1);
219 gss_release_buffer(&min_stat, &name);
222 memcpy(sname, name.value, name.length);
223 sname[name.length] = '\0';
224 gss_release_buffer(&min_stat, &name);
226 if (lustre_svc == LUSTRE_GSS_SVC_MDS)
227 lookup_mapping(sname, nid, &cred->cr_mapped_uid);
229 cred->cr_mapped_uid = -1;
231 realm = strchr(sname, '@');
235 printerr(0, "ERROR: %s has no realm name\n", sname);
239 host = strchr(sname, '/');
243 if (strcmp(sname, GSSD_SERVICE_MGS) == 0) {
244 printerr(0, "forbid %s as a user name\n", sname);
248 /* 1. check host part */
250 if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
251 printerr(0, "ERROR: failed to resolve hostname for "
252 "%s/%s@%s from %016llx\n",
253 sname, host, realm, nid);
257 if (strcasecmp(host, namebuf)) {
258 printerr(0, "ERROR: %s/%s@%s claimed hostname doesn't "
259 "match %s, nid %016llx\n", sname, host, realm,
264 if (!strcmp(sname, GSSD_SERVICE_MDS) ||
265 !strcmp(sname, GSSD_SERVICE_OSS)) {
266 printerr(0, "ERROR: %s@%s from %016llx doesn't "
267 "bind with hostname\n", sname, realm, nid);
272 /* 2. check realm and user */
273 switch (lustre_svc) {
274 case LUSTRE_GSS_SVC_MDS:
275 if (strcasecmp(mds_local_realm, realm)) {
278 /* only allow mapped user from remote realm */
279 if (cred->cr_mapped_uid == -1) {
280 printerr(0, "ERROR: %s%s%s@%s from %016llx "
281 "is remote but without mapping\n",
282 sname, host ? "/" : "",
283 host ? host : "", realm, nid);
287 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
289 cred->cr_usr_root = 1;
290 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
292 cred->cr_usr_mds = 1;
293 } else if (!strcmp(sname, GSSD_SERVICE_OSS)) {
295 cred->cr_usr_oss = 1;
297 pw = getpwnam(sname);
299 cred->cr_uid = pw->pw_uid;
300 printerr(2, "%s resolve to uid %u\n",
301 sname, cred->cr_uid);
302 } else if (cred->cr_mapped_uid != -1) {
303 printerr(2, "user %s from %016llx is "
304 "mapped to %u\n", sname, nid,
305 cred->cr_mapped_uid);
307 printerr(0, "ERROR: invalid user, "
308 "%s/%s@%s from %016llx\n",
309 sname, host, realm, nid);
317 case LUSTRE_GSS_SVC_MGS:
318 if (!strcmp(sname, GSSD_SERVICE_OSS)) {
320 cred->cr_usr_oss = 1;
323 case LUSTRE_GSS_SVC_OSS:
324 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
326 cred->cr_usr_root = 1;
327 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
329 cred->cr_usr_mds = 1;
331 if (cred->cr_uid == -1) {
332 printerr(0, "ERROR: svc %d doesn't accept user %s "
333 "from %016llx\n", lustre_svc, sname, nid);
344 printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
345 lustre_svc_name[lustre_svc], sname,
346 host ? "/" : "", host ? host : "", realm, nid);
351 typedef struct gss_union_ctx_id_t {
353 gss_ctx_id_t internal_ctx_id;
354 } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
356 int handle_sk(struct svc_nego_data *snd)
358 #ifdef HAVE_OPENSSL_SSK
359 struct sk_cred *skc = NULL;
360 struct svc_cred cred;
361 gss_buffer_desc bufs[SK_INIT_BUFFERS];
362 gss_buffer_desc remote_pub_key = GSS_C_EMPTY_BUFFER;
364 uint32_t rc = GSS_S_DEFECTIVE_TOKEN;
369 printerr(3, "Handling sk request\n");
370 memset(bufs, 0, sizeof(gss_buffer_desc) * SK_INIT_BUFFERS);
372 /* See lgss_sk_using_cred() for client side token formation.
373 * Decoding initiator buffers */
374 i = sk_decode_netstring(bufs, SK_INIT_BUFFERS, &snd->in_tok);
375 if (i < SK_INIT_BUFFERS) {
376 printerr(0, "Invalid netstring token received from peer\n");
377 goto cleanup_buffers;
380 /* Allowing for a larger length first buffer in the future */
381 if (bufs[SK_INIT_VERSION].length < sizeof(version)) {
382 printerr(0, "Invalid version received (wrong size)\n");
383 goto cleanup_buffers;
385 memcpy(&version, bufs[SK_INIT_VERSION].value, sizeof(version));
386 version = be32toh(version);
387 if (version != SK_MSG_VERSION) {
388 printerr(0, "Invalid version received: %d\n", version);
389 goto cleanup_buffers;
394 /* target must be a null terminated string */
395 i = bufs[SK_INIT_TARGET].length - 1;
396 target = bufs[SK_INIT_TARGET].value;
397 if (i >= 0 && target[i] != '\0') {
398 printerr(0, "Invalid target from netstring\n");
399 goto cleanup_buffers;
402 if (bufs[SK_INIT_FLAGS].length != sizeof(flags)) {
403 printerr(0, "Invalid flags from netstring\n");
404 goto cleanup_buffers;
406 memcpy(&flags, bufs[SK_INIT_FLAGS].value, sizeof(flags));
408 skc = sk_create_cred(target, snd->nm_name, be32toh(flags));
410 printerr(0, "Failed to create sk credentials\n");
411 goto cleanup_buffers;
414 /* Verify that the peer has used a prime size greater or equal to
415 * the size specified in the key file which may contain only zero
416 * fill but the size specifies the mimimum supported size on
418 if (skc->sc_flags & LGSS_SVC_PRIV &&
419 bufs[SK_INIT_P].length < skc->sc_p.length) {
420 printerr(0, "Peer DHKE prime does not meet the size required "
421 "by keyfile: %zd bits\n", skc->sc_p.length * 8);
422 goto cleanup_buffers;
425 /* Throw out the p from the server and use the wire data */
426 free(skc->sc_p.value);
427 skc->sc_p.value = NULL;
428 skc->sc_p.length = 0;
430 /* Take control of all the allocated buffers from decoding */
431 if (bufs[SK_INIT_RANDOM].length !=
432 sizeof(skc->sc_kctx.skc_peer_random)) {
433 printerr(0, "Invalid size for client random\n");
434 goto cleanup_buffers;
437 memcpy(&skc->sc_kctx.skc_peer_random, bufs[SK_INIT_RANDOM].value,
438 sizeof(skc->sc_kctx.skc_peer_random));
439 skc->sc_p = bufs[SK_INIT_P];
440 remote_pub_key = bufs[SK_INIT_PUB_KEY];
441 skc->sc_nodemap_hash = bufs[SK_INIT_NODEMAP];
442 skc->sc_hmac = bufs[SK_INIT_HMAC];
444 /* Verify HMAC from peer. Ideally this would happen before anything
445 * else but we don't have enough information to lookup key without the
446 * token (fsname and cluster_hash) so it's done after. */
447 rc = sk_verify_hmac(skc, bufs, SK_INIT_BUFFERS - 1, EVP_sha256(),
449 if (rc != GSS_S_COMPLETE) {
450 printerr(0, "HMAC verification error: 0x%x from peer %s\n",
451 rc, libcfs_nid2str((lnet_nid_t)snd->nid));
452 goto cleanup_partial;
455 /* Check that the cluster hash matches the hash of nodemap name */
456 rc = sk_verify_hash(snd->nm_name, EVP_sha256(), &skc->sc_nodemap_hash);
457 if (rc != GSS_S_COMPLETE) {
458 printerr(0, "Cluster hash failed validation: 0x%x\n", rc);
459 goto cleanup_partial;
462 rc = sk_gen_params(skc);
463 if (rc != GSS_S_COMPLETE) {
464 printerr(0, "Failed to generate DH params for responder\n");
465 goto cleanup_partial;
467 if (sk_compute_dh_key(skc, &remote_pub_key)) {
468 printerr(0, "Failed to compute session key from DH params\n");
469 goto cleanup_partial;
472 /* Cleanup init buffers we have copied or don't need anymore */
473 free(bufs[SK_INIT_VERSION].value);
474 free(bufs[SK_INIT_RANDOM].value);
475 free(bufs[SK_INIT_TARGET].value);
476 free(bufs[SK_INIT_FLAGS].value);
478 /* Server reply contains the servers public key, random, and HMAC */
479 version = htobe32(SK_MSG_VERSION);
480 bufs[SK_RESP_VERSION].value = &version;
481 bufs[SK_RESP_VERSION].length = sizeof(version);
482 bufs[SK_RESP_RANDOM].value = &skc->sc_kctx.skc_host_random;
483 bufs[SK_RESP_RANDOM].length = sizeof(skc->sc_kctx.skc_host_random);
484 bufs[SK_RESP_PUB_KEY] = skc->sc_pub_key;
485 if (sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs,
486 SK_RESP_BUFFERS - 1, EVP_sha256(),
488 printerr(0, "Failed to sign parameters\n");
491 bufs[SK_RESP_HMAC] = skc->sc_hmac;
492 if (sk_encode_netstring(bufs, SK_RESP_BUFFERS, &snd->out_tok)) {
493 printerr(0, "Failed to encode netstring for token\n");
496 printerr(2, "Created netstring of %zd bytes\n", snd->out_tok.length);
498 if (sk_session_kdf(skc, snd->nid, &snd->in_tok, &snd->out_tok)) {
499 printerr(0, "Failed to calulate derviced session key\n");
502 if (sk_compute_keys(skc)) {
503 printerr(0, "Failed to compute HMAC and encryption keys\n");
506 if (sk_serialize_kctx(skc, &snd->ctx_token)) {
507 printerr(0, "Failed to serialize context for kernel\n");
511 snd->out_handle.length = sizeof(snd->handle_seq);
512 memcpy(snd->out_handle.value, &snd->handle_seq,
513 sizeof(snd->handle_seq));
514 snd->maj_stat = GSS_S_COMPLETE;
516 /* fix credentials */
517 memset(&cred, 0, sizeof(cred));
518 cred.cr_mapped_uid = -1;
520 if (skc->sc_flags & LGSS_ROOT_CRED_ROOT)
521 cred.cr_usr_root = 1;
522 if (skc->sc_flags & LGSS_ROOT_CRED_MDT)
524 if (skc->sc_flags & LGSS_ROOT_CRED_OST)
527 do_svc_downcall(&snd->out_handle, &cred, snd->mech, &snd->ctx_token);
529 /* cleanup ctx_token, out_tok is cleaned up in handle_channel_req */
530 free(remote_pub_key.value);
531 free(snd->ctx_token.value);
532 snd->ctx_token.length = 0;
534 printerr(3, "sk returning success\n");
538 for (i = 0; i < SK_INIT_BUFFERS; i++)
545 free(bufs[SK_INIT_VERSION].value);
546 free(bufs[SK_INIT_RANDOM].value);
547 free(bufs[SK_INIT_TARGET].value);
548 free(bufs[SK_INIT_FLAGS].value);
549 free(remote_pub_key.value);
556 if (snd->ctx_token.value) {
557 free(snd->ctx_token.value);
558 snd->ctx_token.value = 0;
559 snd->ctx_token.length = 0;
561 free(remote_pub_key.value);
563 printerr(3, "sk returning failure\n");
564 #else /* !HAVE_OPENSSL_SSK */
565 printerr(0, "ERROR: shared key subflavour is not enabled\n");
566 #endif /* HAVE_OPENSSL_SSK */
570 int handle_null(struct svc_nego_data *snd)
572 struct svc_cred cred;
576 /* null just uses the same token as the return token and for
577 * for sending to the kernel. It is a single uint64_t. */
578 if (snd->in_tok.length != sizeof(uint64_t)) {
579 snd->maj_stat = GSS_S_DEFECTIVE_TOKEN;
580 printerr(0, "Invalid token size (%zd) received\n",
584 snd->out_tok.length = snd->in_tok.length;
585 snd->out_tok.value = malloc(snd->out_tok.length);
586 if (!snd->out_tok.value) {
587 snd->maj_stat = GSS_S_FAILURE;
588 printerr(0, "Failed to allocate out_tok\n");
592 snd->ctx_token.length = snd->in_tok.length;
593 snd->ctx_token.value = malloc(snd->ctx_token.length);
594 if (!snd->ctx_token.value) {
595 snd->maj_stat = GSS_S_FAILURE;
596 printerr(0, "Failed to allocate ctx_token\n");
600 snd->out_handle.length = sizeof(snd->handle_seq);
601 memcpy(snd->out_handle.value, &snd->handle_seq,
602 sizeof(snd->handle_seq));
603 snd->maj_stat = GSS_S_COMPLETE;
605 memcpy(&tmp, snd->in_tok.value, sizeof(tmp));
607 flags = (uint32_t)(tmp & 0x00000000ffffffff);
608 memset(&cred, 0, sizeof(cred));
609 cred.cr_mapped_uid = -1;
611 if (flags & LGSS_ROOT_CRED_ROOT)
612 cred.cr_usr_root = 1;
613 if (flags & LGSS_ROOT_CRED_MDT)
615 if (flags & LGSS_ROOT_CRED_OST)
618 do_svc_downcall(&snd->out_handle, &cred, snd->mech, &snd->ctx_token);
620 /* cleanup ctx_token, out_tok is cleaned up in handle_channel_req */
621 free(snd->ctx_token.value);
622 snd->ctx_token.length = 0;
627 static int handle_krb(struct svc_nego_data *snd)
630 gss_name_t client_name;
631 gss_buffer_desc ignore_out_tok = {.value = NULL};
632 gss_OID mech = GSS_C_NO_OID;
633 gss_cred_id_t svc_cred;
634 u_int32_t ignore_min_stat;
635 struct svc_cred cred;
637 svc_cred = gssd_select_svc_cred(snd->lustre_svc);
639 printerr(0, "no service credential for svc %u\n",
644 snd->maj_stat = gss_accept_sec_context(&snd->min_stat, &snd->ctx,
645 svc_cred, &snd->in_tok,
646 GSS_C_NO_CHANNEL_BINDINGS,
648 &snd->out_tok, &ret_flags, NULL,
651 if (snd->maj_stat == GSS_S_CONTINUE_NEEDED) {
652 printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n");
654 /* Save the context handle for future calls */
655 snd->out_handle.length = sizeof(snd->ctx);
656 memcpy(snd->out_handle.value, &snd->ctx, sizeof(snd->ctx));
658 } else if (snd->maj_stat != GSS_S_COMPLETE) {
659 printerr(0, "WARNING: gss_accept_sec_context failed\n");
660 pgsserr("handle_krb: gss_accept_sec_context",
661 snd->maj_stat, snd->min_stat, mech);
665 if (get_ids(client_name, mech, &cred, snd->nid, snd->lustre_svc)) {
666 /* get_ids() prints error msg */
667 snd->maj_stat = GSS_S_BAD_NAME; /* XXX ? */
668 gss_release_name(&ignore_min_stat, &client_name);
671 gss_release_name(&ignore_min_stat, &client_name);
673 /* Context complete. Pass handle_seq in out_handle to use
674 * for context lookup in the kernel. */
675 snd->out_handle.length = sizeof(snd->handle_seq);
676 memcpy(snd->out_handle.value, &snd->handle_seq,
677 sizeof(snd->handle_seq));
679 /* kernel needs ctx to calculate verifier on null response, so
680 * must give it context before doing null call: */
681 if (serialize_context_for_kernel(snd->ctx, &snd->ctx_token, mech)) {
682 printerr(0, "WARNING: handle_krb: "
683 "serialize_context_for_kernel failed\n");
684 snd->maj_stat = GSS_S_FAILURE;
687 /* We no longer need the gss context */
688 gss_delete_sec_context(&ignore_min_stat, &snd->ctx, &ignore_out_tok);
689 do_svc_downcall(&snd->out_handle, &cred, mech, &snd->ctx_token);
694 if (snd->ctx != GSS_C_NO_CONTEXT)
695 gss_delete_sec_context(&ignore_min_stat, &snd->ctx,
702 * return -1 only if we detect error during reading from upcall channel,
703 * all other cases return 0.
705 int handle_channel_request(FILE *f)
707 char in_tok_buf[TOKEN_BUF_SIZE];
708 char in_handle_buf[15];
709 char out_handle_buf[15];
710 gss_buffer_desc ctx_token = {.value = NULL},
711 null_token = {.value = NULL};
712 uint32_t lustre_mech;
718 u_int32_t ignore_min_stat;
719 struct svc_nego_data snd = {
720 .in_tok.value = in_tok_buf,
721 .in_handle.value = in_handle_buf,
722 .out_handle.value = out_handle_buf,
723 .maj_stat = GSS_S_FAILURE,
724 .ctx = GSS_C_NO_CONTEXT,
727 printerr(2, "handling request\n");
728 if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
729 printerr(0, "WARNING: failed reading request\n");
735 /* see rsi_request() for the format of data being input here */
736 qword_get(&cp, (char *)&snd.lustre_svc, sizeof(snd.lustre_svc));
738 /* lustre_svc is the svc and gss subflavor */
739 lustre_mech = (snd.lustre_svc & LUSTRE_GSS_MECH_MASK) >>
740 LUSTRE_GSS_MECH_SHIFT;
741 snd.lustre_svc = snd.lustre_svc & LUSTRE_GSS_SVC_MASK;
742 switch (lustre_mech) {
745 static time_t next_krb;
747 if (time(NULL) > next_krb) {
748 printerr(1, "warning: Request for kerberos but "
749 "service support not enabled\n");
750 next_krb = time(NULL) + 3600;
758 static time_t next_null;
760 if (time(NULL) > next_null) {
761 printerr(1, "warning: Request for gssnull but "
762 "service support not enabled\n");
763 next_null = time(NULL) + 3600;
771 static time_t next_ssk;
773 if (time(NULL) > next_ssk) {
774 printerr(1, "warning: Request for SSK but "
775 "service support not %s\n",
776 #ifdef HAVE_OPENSSL_SSK
782 next_ssk = time(NULL) + 3600;
790 printerr(0, "WARNING: invalid mechanism recevied: %d\n",
796 qword_get(&cp, (char *)&snd.nid, sizeof(snd.nid));
797 qword_get(&cp, (char *)&snd.handle_seq, sizeof(snd.handle_seq));
798 qword_get(&cp, snd.nm_name, sizeof(snd.nm_name));
799 printerr(2, "handling req: svc %u, nid %016llx, idx %"PRIx64" nodemap "
800 "%s\n", snd.lustre_svc, snd.nid, snd.handle_seq, snd.nm_name);
802 get_len = qword_get(&cp, snd.in_handle.value, sizeof(in_handle_buf));
804 printerr(0, "WARNING: failed parsing request\n");
807 snd.in_handle.length = (size_t)get_len;
809 printerr(3, "in_handle:\n");
810 print_hexl(3, snd.in_handle.value, snd.in_handle.length);
812 get_len = qword_get(&cp, snd.in_tok.value, sizeof(in_tok_buf));
814 printerr(0, "WARNING: failed parsing request\n");
817 snd.in_tok.length = (size_t)get_len;
819 printerr(3, "in_tok:\n");
820 print_hexl(3, snd.in_tok.value, snd.in_tok.length);
822 if (snd.in_handle.length != 0) { /* CONTINUE_INIT case */
823 if (snd.in_handle.length != sizeof(snd.ctx)) {
824 printerr(0, "WARNING: input handle has unexpected "
825 "length %zu\n", snd.in_handle.length);
828 /* in_handle is the context id stored in the out_handle
829 * for the GSS_S_CONTINUE_NEEDED case below. */
830 memcpy(&snd.ctx, snd.in_handle.value, snd.in_handle.length);
833 if (lustre_mech == LGSS_MECH_KRB5)
834 rc = handle_krb(&snd);
835 else if (lustre_mech == LGSS_MECH_SK)
836 rc = handle_sk(&snd);
837 else if (lustre_mech == LGSS_MECH_NULL)
838 rc = handle_null(&snd);
840 printerr(0, "WARNING: Received or request for"
841 "subflavor that is not enabled: %d\n", lustre_mech);
844 /* Failures send a null token */
846 send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
847 snd.min_stat, &snd.out_handle, &snd.out_tok);
849 send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
850 snd.min_stat, &null_token, &null_token);
852 /* cleanup buffers */
853 if (snd.ctx_token.value != NULL)
854 free(ctx_token.value);
855 if (snd.out_tok.value != NULL)
856 gss_release_buffer(&ignore_min_stat, &snd.out_tok);
858 /* For junk wire data just ignore */