+ if (snd->ctx != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&ignore_min_stat, &snd->ctx,
+ &ignore_out_tok);
+
+ return 1;
+}
+
+/*
+ * return -1 only if we detect error during reading from upcall channel,
+ * all other cases return 0.
+ */
+int handle_channel_request(FILE *f)
+{
+ char in_tok_buf[TOKEN_BUF_SIZE];
+ char in_handle_buf[15];
+ char out_handle_buf[15];
+ gss_buffer_desc ctx_token = {.value = NULL},
+ null_token = {.value = NULL};
+ uint32_t lustre_mech;
+ static char *lbuf;
+ static int lbuflen;
+ static char *cp;
+ int get_len;
+ int rc = 1;
+ u_int32_t ignore_min_stat;
+ struct svc_nego_data snd = {
+ .in_tok.value = in_tok_buf,
+ .in_handle.value = in_handle_buf,
+ .out_handle.value = out_handle_buf,
+ .maj_stat = GSS_S_FAILURE,
+ .ctx = GSS_C_NO_CONTEXT,
+ };
+
+ printerr(2, "handling request\n");
+ if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
+ printerr(0, "WARNING: failed reading request\n");
+ return -1;
+ }
+
+ cp = lbuf;
+
+ /* see rsi_request() for the format of data being input here */
+ qword_get(&cp, (char *)&snd.lustre_svc, sizeof(snd.lustre_svc));
+
+ /* lustre_svc is the svc and gss subflavor */
+ lustre_mech = (snd.lustre_svc & LUSTRE_GSS_MECH_MASK) >>
+ LUSTRE_GSS_MECH_SHIFT;
+ snd.lustre_svc = snd.lustre_svc & LUSTRE_GSS_SVC_MASK;
+ switch (lustre_mech) {
+ case LGSS_MECH_KRB5:
+ if (!krb_enabled) {
+ printerr(1, "WARNING: Request for kerberos but service "
+ "support not enabled\n");
+ goto ignore;
+ }
+ snd.mech = &krb5oid;
+ break;
+ case LGSS_MECH_NULL:
+ if (!null_enabled) {
+ printerr(1, "WARNING: Request for gssnull but service "
+ "support not enabled\n");
+ goto ignore;
+ }
+ snd.mech = &nulloid;
+ break;
+ case LGSS_MECH_SK:
+ if (!sk_enabled) {
+ printerr(1, "WARNING: Request for sk but service "
+ "support not enabled\n");
+ goto ignore;
+ }
+ snd.mech = &skoid;
+ break;
+ default:
+ printerr(0, "WARNING: invalid mechanism recevied: %d\n",
+ lustre_mech);
+ goto out_err;
+ break;
+ }
+
+ qword_get(&cp, (char *)&snd.nid, sizeof(snd.nid));
+ qword_get(&cp, (char *)&snd.handle_seq, sizeof(snd.handle_seq));
+ qword_get(&cp, snd.nm_name, sizeof(snd.nm_name));
+ printerr(2, "handling req: svc %u, nid %016llx, idx %"PRIx64" nodemap "
+ "%s\n", snd.lustre_svc, snd.nid, snd.handle_seq, snd.nm_name);
+
+ get_len = qword_get(&cp, snd.in_handle.value, sizeof(in_handle_buf));
+ if (get_len < 0) {
+ printerr(0, "WARNING: failed parsing request\n");
+ goto out_err;
+ }
+ snd.in_handle.length = (size_t)get_len;
+
+ printerr(3, "in_handle:\n");
+ print_hexl(3, snd.in_handle.value, snd.in_handle.length);
+
+ get_len = qword_get(&cp, snd.in_tok.value, sizeof(in_tok_buf));
+ if (get_len < 0) {
+ printerr(0, "WARNING: failed parsing request\n");
+ goto out_err;
+ }
+ snd.in_tok.length = (size_t)get_len;
+
+ printerr(3, "in_tok:\n");
+ print_hexl(3, snd.in_tok.value, snd.in_tok.length);
+
+ if (snd.in_handle.length != 0) { /* CONTINUE_INIT case */
+ if (snd.in_handle.length != sizeof(snd.ctx)) {
+ printerr(0, "WARNING: input handle has unexpected "
+ "length %zu\n", snd.in_handle.length);
+ goto out_err;
+ }
+ /* in_handle is the context id stored in the out_handle
+ * for the GSS_S_CONTINUE_NEEDED case below. */
+ memcpy(&snd.ctx, snd.in_handle.value, snd.in_handle.length);
+ }
+
+ if (lustre_mech == LGSS_MECH_KRB5)
+ rc = handle_krb(&snd);
+ else if (lustre_mech == LGSS_MECH_SK)
+ rc = handle_sk(&snd);
+ else if (lustre_mech == LGSS_MECH_NULL)
+ rc = handle_null(&snd);
+ else
+ printerr(0, "WARNING: Received or request for"
+ "subflavor that is not enabled: %d\n", lustre_mech);
+
+out_err:
+ /* Failures send a null token */
+ if (rc == 0)
+ send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
+ snd.min_stat, &snd.out_handle, &snd.out_tok);
+ else
+ send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
+ snd.min_stat, &null_token, &null_token);
+
+ /* cleanup buffers */
+ if (snd.ctx_token.value != NULL)
+ free(ctx_token.value);
+ if (snd.out_tok.value != NULL)
+ gss_release_buffer(&ignore_min_stat, &snd.out_tok);
+
+ /* For junk wire data just ignore */
+ignore:
+ return 0;