4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2014, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lustre/utils/gss/lgss_keyring.c
34 * user-space upcall to create GSS context, using keyring interface to kernel
36 * Author: Eric Mei <ericm@clusterfs.com>
40 #include <sys/types.h>
51 #include <gssapi/gssapi.h>
53 #include <libcfs/util/param.h>
54 #include <libcfs/util/string.h>
56 #include "lgss_utils.h"
57 #include "write_bytes.h"
61 * gss target string of lustre service we are negotiating for
63 static char *g_service = NULL;
66 * all data about negotiation
68 struct lgss_nego_data {
69 uint32_t lnd_established:1;
76 gss_OID lnd_mech; /* mech OID */
77 gss_name_t lnd_svc_name; /* service name */
78 unsigned int lnd_req_flags; /* request flags */
79 gss_cred_id_t lnd_cred; /* credential */
80 gss_ctx_id_t lnd_ctx; /* session context */
81 gss_buffer_desc lnd_rmt_ctx; /* remote handle of context */
82 gss_buffer_desc lnd_ctx_token; /* context token for kernel */
83 uint32_t lnd_seq_win; /* sequence window */
90 * context creation response
92 struct lgss_init_res {
93 gss_buffer_desc gr_ctx; /* context handle */
94 unsigned int gr_major; /* major status */
95 unsigned int gr_minor; /* minor status */
96 unsigned int gr_win; /* sequence window */
97 gss_buffer_desc gr_token; /* token */
100 struct keyring_upcall_param {
109 uint64_t kup_selfnid;
113 unsigned int kup_is_root:1,
119 /****************************************
120 * child process: gss negotiation *
121 ****************************************/
123 int do_nego_rpc(struct lgss_nego_data *lnd,
124 gss_buffer_desc *gss_token,
125 struct lgss_init_res *gr)
127 struct lgssd_ioctl_param param;
135 logmsg(LL_TRACE, "start negotiation rpc\n");
137 pw = getpwuid(lnd->lnd_uid);
139 logmsg(LL_ERR, "no uid %u in local user database\n",
144 param.version = GSSD_INTERFACE_VERSION;
145 param.secid = lnd->lnd_secid;
146 param.uuid = lnd->lnd_uuid;
147 param.lustre_svc = lnd->lnd_lsvc;
148 param.uid = lnd->lnd_uid;
149 param.gid = pw->pw_gid;
150 param.send_token_size = gss_token->length;
151 param.send_token = (char *) gss_token->value;
152 param.reply_buf_size = sizeof(outbuf);
153 param.reply_buf = outbuf;
155 rc = cfs_get_param_paths(&path, "sptlrpc/gss/init_channel");
159 logmsg(LL_TRACE, "to open %s\n", path.gl_pathv[0]);
161 fd = open(path.gl_pathv[0], O_WRONLY);
163 logmsg(LL_ERR, "can't open %s\n", path.gl_pathv[0]);
168 logmsg(LL_TRACE, "to down-write\n");
170 ret = write(fd, ¶m, sizeof(param));
172 if (ret != sizeof(param)) {
173 logmsg(LL_ERR, "lustre ioctl err: %s\n", strerror(errno));
178 logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n");
180 logmsg(LL_ERR, "status: %ld (%s)\n",
181 param.status, strerror((int)(-param.status)));
183 /* kernel return -ETIMEDOUT means the rpc timedout, we should
184 * notify the caller to reinitiate the gss negotiation, by
185 * returning -ERESTART
187 if (param.status == -ETIMEDOUT)
194 p = (unsigned int *)outbuf;
200 gr->gr_ctx.length = *p++;
201 gr->gr_ctx.value = malloc(gr->gr_ctx.length);
202 if (gr->gr_ctx.value == NULL)
204 memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
205 p += (((gr->gr_ctx.length + 3) & ~3) / 4);
207 gr->gr_token.length = *p++;
208 gr->gr_token.value = malloc(gr->gr_token.length);
209 if (gr->gr_token.value == NULL) {
210 free(gr->gr_ctx.value);
213 memcpy(gr->gr_token.value, p, gr->gr_token.length);
214 p += (((gr->gr_token.length + 3) & ~3) / 4);
216 logmsg(LL_DEBUG, "do_nego_rpc: receive handle len %zu, token len %zu, "
217 "res %d\n", gr->gr_ctx.length, gr->gr_token.length, res);
219 cfs_free_param_data(&path);
223 /* This is used by incomplete GSSAPI implementations that can't use
224 * gss_init_sec_context and will parse the token themselves (gssnull and sk).
225 * Callers should have cred->lc_mech_token pointing to a gss_buffer_desc
226 * token to send to the peer as part of the SEC_CTX_INIT operation. The return
227 * RPC's token with be in gr.gr_token which is validated using
228 * lgss_validate_cred. */
229 static int lgssc_negotiation_manual(struct lgss_nego_data *lnd,
230 struct lgss_cred *cred)
232 struct lgss_init_res gr;
236 logmsg(LL_TRACE, "starting gss negotation\n");
237 memset(&gr, 0, sizeof(gr));
239 lnd->lnd_rpc_err = do_nego_rpc(lnd, &cred->lc_mech_token, &gr);
240 if (lnd->lnd_rpc_err) {
241 logmsg(LL_ERR, "negotiation rpc error %d\n", lnd->lnd_rpc_err);
242 rc = lnd->lnd_rpc_err;
246 if (gr.gr_major == GSS_S_CONTINUE_NEEDED) {
250 } else if (gr.gr_major != GSS_S_COMPLETE) {
251 lnd->lnd_gss_err = gr.gr_major;
252 logmsg(LL_ERR, "negotiation gss error %x\n", lnd->lnd_gss_err);
257 if (gr.gr_ctx.length == 0 || gr.gr_token.length == 0) {
258 logmsg(LL_ERR, "zero length context or token received\n");
263 rc = lgss_validate_cred(cred, &gr.gr_token, &lnd->lnd_ctx_token);
265 logmsg(LL_ERR, "peer token failed validation\n");
269 lnd->lnd_established = 1;
270 lnd->lnd_seq_win = gr.gr_win;
271 lnd->lnd_rmt_ctx = gr.gr_ctx;
273 if (gr.gr_token.length != 0)
274 gss_release_buffer(&min_stat, &gr.gr_token);
276 logmsg(LL_DEBUG, "successfully negotiated a context\n");
280 if (gr.gr_ctx.length != 0)
281 gss_release_buffer(&min_stat, &gr.gr_ctx);
282 if (gr.gr_token.length != 0)
283 gss_release_buffer(&min_stat, &gr.gr_token);
289 * if return error, the lnd_rpc_err or lnd_gss_err is set.
291 static int lgssc_negotiation(struct lgss_nego_data *lnd)
293 struct lgss_init_res gr;
294 gss_buffer_desc *recv_tokenp, send_token;
295 OM_uint32 maj_stat, min_stat, ret_flags;
297 logmsg(LL_TRACE, "start gss negotiation\n");
299 /* GSS context establishment loop. */
300 memset(&gr, 0, sizeof(gr));
301 recv_tokenp = GSS_C_NO_BUFFER;
304 maj_stat = gss_init_sec_context(&min_stat,
313 NULL, /* used mech */
316 NULL); /* time rec */
318 if (recv_tokenp != GSS_C_NO_BUFFER) {
319 gss_release_buffer(&min_stat, &gr.gr_token);
320 recv_tokenp = GSS_C_NO_BUFFER;
323 if (maj_stat != GSS_S_COMPLETE &&
324 maj_stat != GSS_S_CONTINUE_NEEDED) {
325 lnd->lnd_gss_err = maj_stat;
327 logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
328 "failed init context");
332 if (send_token.length != 0) {
333 memset(&gr, 0, sizeof(gr));
335 lnd->lnd_rpc_err = do_nego_rpc(lnd, &send_token, &gr);
336 gss_release_buffer(&min_stat, &send_token);
338 if (lnd->lnd_rpc_err) {
339 logmsg(LL_ERR, "negotiation rpc error: %d\n",
344 if (gr.gr_major != GSS_S_COMPLETE &&
345 gr.gr_major != GSS_S_CONTINUE_NEEDED) {
346 lnd->lnd_gss_err = gr.gr_major;
348 logmsg(LL_ERR, "negotiation gss error %x\n",
353 if (gr.gr_ctx.length != 0) {
354 if (lnd->lnd_rmt_ctx.value)
355 gss_release_buffer(&min_stat,
357 lnd->lnd_rmt_ctx = gr.gr_ctx;
360 if (gr.gr_token.length != 0) {
361 if (maj_stat != GSS_S_CONTINUE_NEEDED)
363 recv_tokenp = &gr.gr_token;
367 /* GSS_S_COMPLETE => check gss header verifier,
368 * usually checked in gss_validate
370 if (maj_stat == GSS_S_COMPLETE) {
371 lnd->lnd_established = 1;
372 lnd->lnd_seq_win = gr.gr_win;
377 /* End context negotiation loop. */
378 if (!lnd->lnd_established) {
379 if (gr.gr_token.length != 0)
380 gss_release_buffer(&min_stat, &gr.gr_token);
382 if (lnd->lnd_gss_err == GSS_S_COMPLETE)
383 lnd->lnd_rpc_err = -EACCES;
385 logmsg(LL_ERR, "context negotiation failed\n");
389 logmsg(LL_DEBUG, "successfully negotiated a context\n");
394 * if return error, the lnd_rpc_err or lnd_gss_err is set.
396 static int lgssc_init_nego_data(struct lgss_nego_data *lnd,
397 struct keyring_upcall_param *kup,
400 gss_buffer_desc sname;
401 OM_uint32 maj_stat, min_stat;
403 memset(lnd, 0, sizeof(*lnd));
405 lnd->lnd_secid = kup->kup_secid;
406 lnd->lnd_uid = kup->kup_uid;
407 lnd->lnd_lsvc = kup->kup_svc | mech << LUSTRE_GSS_MECH_SHIFT;
408 lnd->lnd_uuid = kup->kup_tgt;
410 lnd->lnd_established = 0;
411 lnd->lnd_svc_name = GSS_C_NO_NAME;
412 lnd->lnd_cred = GSS_C_NO_CREDENTIAL;
413 lnd->lnd_ctx = GSS_C_NO_CONTEXT;
414 lnd->lnd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
415 lnd->lnd_seq_win = 0;
419 lnd->lnd_mech = (gss_OID)&krb5oid;
420 lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG;
423 lnd->lnd_mech = (gss_OID)&nulloid;
425 #ifdef HAVE_OPENSSL_SSK
427 lnd->lnd_mech = (gss_OID)&skoid;
428 lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG;
432 logmsg(LL_ERR, "invalid mech: %d\n", mech);
433 lnd->lnd_rpc_err = -EACCES;
437 sname.value = g_service;
438 sname.length = strlen(g_service);
440 maj_stat = gss_import_name(&min_stat, &sname,
441 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
443 if (maj_stat != GSS_S_COMPLETE) {
444 logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
445 "can't import svc name");
446 lnd->lnd_gss_err = maj_stat;
453 void lgssc_fini_nego_data(struct lgss_nego_data *lnd)
455 OM_uint32 maj_stat, min_stat;
457 if (lnd->lnd_svc_name != GSS_C_NO_NAME) {
458 maj_stat = gss_release_name(&min_stat, &lnd->lnd_svc_name);
459 if (maj_stat != GSS_S_COMPLETE)
460 logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
461 "can't release service name");
464 if (lnd->lnd_cred != GSS_C_NO_CREDENTIAL) {
465 maj_stat = gss_release_cred(&min_stat, &lnd->lnd_cred);
466 if (maj_stat != GSS_S_COMPLETE)
467 logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
468 "can't release credential");
473 int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error)
479 logmsg(LL_TRACE, "revoking kernel key %08x\n", keyid);
482 end = buf + sizeof(buf);
484 WRITE_BYTES(&p, end, seqwin);
485 WRITE_BYTES(&p, end, rpc_error);
486 WRITE_BYTES(&p, end, gss_error);
489 if (keyctl_update(keyid, buf, p - buf)) {
490 if (errno != EAGAIN) {
491 logmsg(LL_ERR, "revoke key %08x: %s\n",
492 keyid, strerror(errno));
496 logmsg(LL_WARN, "key %08x: revoking too soon, try again\n",
502 logmsg(LL_INFO, "key %08x: revoked\n", keyid);
507 int update_kernel_key(key_serial_t keyid,
508 struct lgss_nego_data *lnd,
509 gss_buffer_desc *ctx_token)
511 char *buf = NULL, *p = NULL, *end = NULL;
512 unsigned int buf_size = 0;
515 logmsg(LL_TRACE, "updating kernel key %08x\n", keyid);
517 buf_size = sizeof(lnd->lnd_seq_win) +
518 sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length +
519 sizeof(ctx_token->length) + ctx_token->length;
520 buf = malloc(buf_size);
522 logmsg(LL_ERR, "key %08x: can't alloc update buf: size %d\n",
528 end = buf + buf_size;
531 if (WRITE_BYTES(&p, end, lnd->lnd_seq_win))
533 if (write_buffer(&p, end, &lnd->lnd_rmt_ctx))
535 if (write_buffer(&p, end, ctx_token))
539 if (keyctl_update(keyid, buf, p - buf)) {
540 if (errno != EAGAIN) {
541 logmsg(LL_ERR, "update key %08x: %s\n",
542 keyid, strerror(errno));
546 logmsg(LL_DEBUG, "key %08x: updating too soon, try again\n",
553 logmsg(LL_DEBUG, "key %08x: updated\n", keyid);
559 static int lgssc_kr_negotiate_krb(key_serial_t keyid, struct lgss_cred *cred,
560 struct keyring_upcall_param *kup)
562 struct lgss_nego_data lnd;
566 memset(&lnd, 0, sizeof(lnd));
568 if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
569 logmsg(LL_ERR, "key %08x: failed to construct service "
571 error_kernel_key(keyid, -EACCES, 0);
575 if (lgss_using_cred(cred)) {
576 logmsg(LL_ERR, "key %08x: can't using cred\n", keyid);
577 error_kernel_key(keyid, -EACCES, 0);
581 if (lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n)) {
582 logmsg(LL_ERR, "key %08x: failed to initialize "
583 "negotiation data\n", keyid);
584 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
588 rc = lgssc_negotiation(&lnd);
590 logmsg(LL_ERR, "key %08x: failed to negotiation\n", keyid);
591 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
595 rc = serialize_context_for_kernel(lnd.lnd_ctx, &lnd.lnd_ctx_token,
598 logmsg(LL_ERR, "key %08x: failed to export context\n", keyid);
599 error_kernel_key(keyid, rc, lnd.lnd_gss_err);
603 rc = update_kernel_key(keyid, &lnd, &lnd.lnd_ctx_token);
608 logmsg(LL_INFO, "key %08x for user %u is updated OK!\n",
609 keyid, kup->kup_uid);
611 if (lnd.lnd_ctx_token.length != 0)
612 gss_release_buffer(&min_stat, &lnd.lnd_ctx_token);
614 lgssc_fini_nego_data(&lnd);
617 lgss_release_cred(cred);
621 static int lgssc_kr_negotiate_manual(key_serial_t keyid, struct lgss_cred *cred,
622 struct keyring_upcall_param *kup)
624 struct lgss_nego_data lnd;
629 memset(&lnd, 0, sizeof(lnd));
631 rc = lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid);
633 logmsg(LL_ERR, "key %08x: failed to construct service "
635 error_kernel_key(keyid, -EACCES, 0);
639 rc = lgss_using_cred(cred);
641 logmsg(LL_ERR, "key %08x: can't use cred\n", keyid);
642 error_kernel_key(keyid, -EACCES, 0);
646 rc = lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n);
648 logmsg(LL_ERR, "key %08x: failed to initialize "
649 "negotiation data\n", keyid);
650 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
655 * Handles the negotiation but then calls lgss_validate to make sure
656 * the token is valid. It also populates the lnd_ctx_token for the
657 * update to the kernel key
659 rc = lgssc_negotiation_manual(&lnd, cred);
661 logmsg(LL_ERR, "Failed negotiation must retry\n");
665 logmsg(LL_ERR, "key %08x: failed to negotiate\n", keyid);
666 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
670 rc = update_kernel_key(keyid, &lnd, &lnd.lnd_ctx_token);
674 logmsg(LL_INFO, "key %08x for user %u is updated OK!\n",
675 keyid, kup->kup_uid);
677 if (lnd.lnd_ctx_token.length != 0)
678 gss_release_buffer(&min_stat, &lnd.lnd_ctx_token);
680 lgssc_fini_nego_data(&lnd);
683 lgss_release_cred(cred);
688 * note we inherited assumed authority from parent process
690 static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
691 struct keyring_upcall_param *kup)
695 logmsg(LL_TRACE, "child start on behalf of key %08x: "
696 "cred %p, uid %u, svc %u, nid %"PRIx64", uids: %u:%u/%u:%u\n",
697 keyid, cred, cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid,
698 kup->kup_uid, kup->kup_gid, kup->kup_fsuid, kup->kup_fsgid);
700 switch (cred->lc_mech->lmt_mech_n) {
703 rc = lgssc_kr_negotiate_manual(keyid, cred, kup);
707 rc = lgssc_kr_negotiate_krb(keyid, cred, kup);
715 * call out info format: s[:s]...
717 * [1]: mech_name (string)
720 * [4]: flags (string) FMT: r-root; m-mdt; o-ost
721 * [5]: svc type (char)
722 * [6]: lustre_svc (int)
723 * [7]: target_nid (uint64)
724 * [8]: target_uuid (string)
725 * [9]: self_nid (uint64)
728 static int parse_callout_info(const char *coinfo,
729 struct keyring_upcall_param *uparam)
731 const int nargs = 11;
738 length = strlen(coinfo) + 1;
740 logmsg(LL_ERR, "coinfo too long\n");
743 memcpy(buf, coinfo, length);
745 for (i = 0; i < nargs - 1; i++) {
746 pos = strchr(string, ':');
748 logmsg(LL_ERR, "short of components\n");
758 logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%c,%s,%s,%s,%s,%s\n",
759 data[0], data[1], data[2], data[3], data[4], data[5][0],
760 data[6], data[7], data[8], data[9], data[10]);
762 uparam->kup_secid = strtol(data[0], NULL, 0);
763 strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
764 uparam->kup_uid = strtol(data[2], NULL, 0);
765 uparam->kup_gid = strtol(data[3], NULL, 0);
766 if (strchr(data[4], 'r'))
767 uparam->kup_is_root = 1;
768 if (strchr(data[4], 'm'))
769 uparam->kup_is_mdt = 1;
770 if (strchr(data[4], 'o'))
771 uparam->kup_is_ost = 1;
772 uparam->kup_svc_type = data[5][0];
773 uparam->kup_svc = strtol(data[6], NULL, 0);
774 uparam->kup_nid = strtoll(data[7], NULL, 0);
775 strlcpy(uparam->kup_tgt, data[8], sizeof(uparam->kup_tgt));
776 uparam->kup_selfnid = strtoll(data[9], NULL, 0);
777 uparam->kup_pid = strtol(data[10], NULL, 0);
779 logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u, "
780 "is_root %d, is_mdt %d, is_ost %d, svc type %c, svc %d, "
781 "nid 0x%"PRIx64", tgt %s, self nid 0x%"PRIx64", pid %d\n",
782 uparam->kup_secid, uparam->kup_mech,
783 uparam->kup_uid, uparam->kup_gid,
784 uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost,
785 uparam->kup_svc_type, uparam->kup_svc, uparam->kup_nid,
786 uparam->kup_tgt, uparam->kup_selfnid, uparam->kup_pid);
790 static void set_log_level()
796 if (cfs_get_param_paths(&path,
797 "sptlrpc/gss/lgss_keyring/debug_level") != 0)
799 file = fopen(path.gl_pathv[0], "r");
801 cfs_free_param_data(&path);
805 if (fscanf(file, "%u", &level) != 1)
811 lgss_set_loglevel(level);
813 cfs_free_param_data(&path);
818 static int associate_with_ns(char *path)
822 fd = open(path, O_RDONLY);
832 /****************************************
834 ****************************************/
836 int main(int argc, char *argv[])
838 struct keyring_upcall_param uparam;
841 key_serial_t inst_keyring;
843 struct lgss_mech_type *mech;
844 struct lgss_cred *cred;
847 struct stat parent_ns = { .st_ino = 0 }, caller_ns = { .st_ino = 0 };
852 logmsg(LL_TRACE, "start parsing parameters\n");
854 * parse & sanity check upcall parameters
855 * expected to be called with:
859 * [4]: key description
863 * [8]: thread keyring
864 * [9]: process keyring
865 * [10]: session keyring
867 if (argc != 10 + 1) {
868 logmsg(LL_ERR, "invalid parameter number %d\n", argc);
872 logmsg(LL_INFO, "key %s, desc %s, ugid %s:%s, sring %s, coinfo %s\n",
873 argv[2], argv[4], argv[6], argv[7], argv[10], argv[5]);
875 memset(&uparam, 0, sizeof(uparam));
877 if (strcmp(argv[1], "create") != 0) {
878 logmsg(LL_ERR, "invalid OP %s\n", argv[1]);
882 if (sscanf(argv[2], "%d", &keyid) != 1) {
883 logmsg(LL_ERR, "can't extract KeyID: %s\n", argv[2]);
887 if (sscanf(argv[6], "%d", &uparam.kup_fsuid) != 1) {
888 logmsg(LL_ERR, "can't extract UID: %s\n", argv[6]);
892 if (sscanf(argv[7], "%d", &uparam.kup_fsgid) != 1) {
893 logmsg(LL_ERR, "can't extract GID: %s\n", argv[7]);
897 if (sscanf(argv[10], "%d", &sring) != 1) {
898 logmsg(LL_ERR, "can't extract session keyring: %s\n", argv[10]);
902 if (parse_callout_info(argv[5], &uparam)) {
903 logmsg(LL_ERR, "can't extract callout info: %s\n", argv[5]);
907 logmsg(LL_TRACE, "parsing parameters OK\n");
912 mech = lgss_name2mech(uparam.kup_mech);
914 logmsg(LL_ERR, "key %08x: unsupported mech: %s\n",
915 keyid, uparam.kup_mech);
919 if (lgss_mech_initialize(mech)) {
920 logmsg(LL_ERR, "key %08x: can't initialize mech %s\n",
921 keyid, mech->lmt_name);
925 cred = lgss_create_cred(mech);
927 logmsg(LL_ERR, "key %08x: can't create a new %s cred\n",
928 keyid, mech->lmt_name);
932 cred->lc_uid = uparam.kup_uid;
933 cred->lc_root_flags |= uparam.kup_is_root ? LGSS_ROOT_CRED_ROOT : 0;
934 cred->lc_root_flags |= uparam.kup_is_mdt ? LGSS_ROOT_CRED_MDT : 0;
935 cred->lc_root_flags |= uparam.kup_is_ost ? LGSS_ROOT_CRED_OST : 0;
936 cred->lc_tgt_nid = uparam.kup_nid;
937 cred->lc_tgt_svc = uparam.kup_svc;
938 cred->lc_tgt_uuid = uparam.kup_tgt;
939 cred->lc_svc_type = uparam.kup_svc_type;
940 cred->lc_self_nid = uparam.kup_selfnid;
943 /* Is caller in different namespace? */
944 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
945 if (stat(path, &parent_ns))
946 logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
947 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", uparam.kup_pid);
948 if (stat(path, &caller_ns))
949 logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
950 if (caller_ns.st_ino != parent_ns.st_ino) {
952 * do credentials preparation in caller's namespace
954 if (associate_with_ns(path) != 0) {
955 logmsg(LL_ERR, "failed to attach to pid %d namespace: "
956 "%s\n", uparam.kup_pid, strerror(errno));
959 logmsg(LL_TRACE, "working in namespace of pid %d\n",
962 logmsg(LL_TRACE, "caller's namespace is the same\n");
964 #endif /* HAVE_SETNS */
966 if (lgss_prepare_cred(cred)) {
967 logmsg(LL_ERR, "key %08x: failed to prepare credentials "
968 "for user %d\n", keyid, uparam.kup_uid);
972 /* pre initialize the key. note the keyring linked to is actually of the
973 * original requesting process, not _this_ upcall process. if it's for
974 * root user, don't link to any keyrings because we want fully control
975 * on it, and share it among all root sessions; otherswise link to
978 if (cred->lc_root_flags != 0)
981 inst_keyring = KEY_SPEC_SESSION_KEYRING;
983 if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
984 logmsg(LL_ERR, "instantiate key %08x: %s\n",
985 keyid, strerror(errno));
989 logmsg(LL_TRACE, "instantiated kernel key %08x\n", keyid);
992 * fork a child to do the real gss negotiation
996 logmsg(LL_ERR, "key %08x: can't create child: %s\n",
997 keyid, strerror(errno));
999 } else if (child == 0) {
1000 return lgssc_kr_negotiate(keyid, cred, &uparam);
1003 logmsg(LL_TRACE, "forked child %d\n", child);