1 diff -rNup nfs-utils-1.0.10/configure.in nfs-utils-1.0.10.lustre/configure.in
2 --- nfs-utils-1.0.10/configure.in 2007-05-15 13:02:26.000000000 -0600
3 +++ nfs-utils-1.0.10.lustre/configure.in 2007-05-15 13:00:53.000000000 -0600
4 @@ -17,61 +17,14 @@ AC_ARG_WITH(release,
9 - [ --with-statedir=/foo use state dir /foo [/var/lib/nfs]],
11 - statedir=/var/lib/nfs)
13 -AC_ARG_WITH(statduser,
14 - [AC_HELP_STRING([--with-statduser=rpcuser],
15 - [statd to run under @<:@rpcuser or nobody@:>@]
18 - if test "x$cross_compiling" = "xno"; then
19 - if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
29 - [AC_HELP_STRING([--enable-nfsv3],
30 - [enable support for NFSv3 @<:@default=yes@:>@])],
31 - enable_nfsv3=$enableval,
33 - if test "$enable_nfsv3" = yes; then
34 - AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in])
38 - AC_SUBST(enable_nfsv3)
40 - [AC_HELP_STRING([--enable-nfsv4],
41 - [enable support for NFSv4 @<:@default=yes@:>@])],
42 - enable_nfsv4=$enableval,
44 - if test "$enable_nfsv4" = yes; then
45 - AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in])
52 - AC_SUBST(enable_nfsv4)
53 - AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
55 [AC_HELP_STRING([--enable-gss],
56 [enable support for rpcsec_gss @<:@default=yes@:>@])],
57 enable_gss=$enableval,
59 if test "$enable_gss" = yes; then
60 - AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in])
68 @@ -81,38 +34,6 @@ AC_ARG_ENABLE(gss,
71 AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"])
72 -AC_ARG_ENABLE(kprefix,
73 - [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])],
74 - test "$enableval" = "yes" && kprefix=k,
77 -AC_ARG_ENABLE(secure-statd,
78 - [AC_HELP_STRING([--enable-secure-statd],
79 - [Only lockd can use statd (security)])],
80 - test "$enableval" = "yes" && secure_statd=yes,
82 - if test "$secure_statd" = yes; then
83 - AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.])
85 - AC_SUBST(secure_statd)
86 -AC_ARG_ENABLE(rquotad,
87 - [AC_HELP_STRING([--enable-rquotad],
88 - [enable rquotad @<:@default=yes@:>@])],
89 - enable_rquotad=$enableval,
91 - if test "$enable_rquotad" = yes; then
96 - AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"])
99 - [AC_HELP_STRING([--enable-mount],
100 - [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])],
101 - enable_mount=$enableval,
103 - AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
105 # Check whether user wants TCP wrappers support
107 @@ -155,47 +76,17 @@ AC_CHECK_FUNC(connect, ,
108 AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL))
110 AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
111 -if test "$enable_nfsv4" = yes; then
112 - AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support]))
113 - AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
114 - AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support]))
115 - AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
116 - dnl librpcsecgss already has a dependency on libgssapi,
117 - dnl but we need to make sure we get the right version
118 if test "$enable_gss" = yes; then
119 - PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, ,
120 - [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss. If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig])
123 PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
127 -if test "$knfsd_cv_glibc2" = no; then
128 - AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
134 if test "$enable_gss" = yes; then
135 - dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
136 - AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
137 - AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
138 - dnl the nfs4_set_debug function doesn't appear in all version of the library
139 - AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
140 - AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
141 - [Whether nfs4_set_debug() is present in libnfsidmap]),)
143 dnl Check for Kerberos V5
146 - dnl This is not done until here because we need to have KRBLIBS set
147 - dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
148 - AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
149 - AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
150 - AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
154 dnl *************************************************************
155 @@ -307,35 +198,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
161 - support/export/Makefile
162 - support/include/nfs/Makefile
163 - support/include/rpcsvc/Makefile
164 - support/include/sys/fs/Makefile
165 - support/include/sys/Makefile
166 - support/include/Makefile
167 - support/misc/Makefile
168 - support/nfs/Makefile
170 - tools/getiversion/Makefile
171 - tools/getkversion/Makefile
172 - tools/locktest/Makefile
173 - tools/nlmtest/Makefile
174 - tools/rpcdebug/Makefile
175 - tools/rpcgen/Makefile
177 - utils/exportfs/Makefile
178 - utils/gssd/Makefile
179 - utils/idmapd/Makefile
180 - utils/lockd/Makefile
181 - utils/mount/Makefile
182 - utils/mountd/Makefile
183 - utils/nfsd/Makefile
184 - utils/nfsstat/Makefile
185 - utils/nhfsstone/Makefile
186 - utils/rquotad/Makefile
187 - utils/showmount/Makefile
188 - utils/statd/Makefile])
189 + utils/gssd/Makefile])
192 diff -rNup nfs-utils-1.0.10/Makefile.am nfs-utils-1.0.10.lustre/Makefile.am
193 --- nfs-utils-1.0.10/Makefile.am 2007-05-15 13:02:26.000000000 -0600
194 +++ nfs-utils-1.0.10.lustre/Makefile.am 2007-05-15 13:00:53.000000000 -0600
196 ## Process this file with automake to produce Makefile.in
198 -SUBDIRS = tools support utils linux-nfs
201 MAINTAINERCLEANFILES = Makefile.in
203 diff -rNup nfs-utils-1.0.10/utils/gssd/cacheio.c nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c
204 --- nfs-utils-1.0.10/utils/gssd/cacheio.c 2006-08-07 00:40:50.000000000 -0600
205 +++ nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c 2007-05-15 13:01:35.000000000 -0600
206 @@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in
208 while (*bp == ' ') bp++;
211 +// why should we clear *dest???
216 diff -rNup nfs-utils-1.0.10/utils/gssd/context.c nfs-utils-1.0.10.lustre/utils/gssd/context.c
217 --- nfs-utils-1.0.10/utils/gssd/context.c 2006-08-07 00:40:50.000000000 -0600
218 +++ nfs-utils-1.0.10.lustre/utils/gssd/context.c 2007-05-15 13:01:35.000000000 -0600
222 #include <gssapi/gssapi.h>
223 -#include <rpc/rpc.h>
224 -#include <rpc/auth_gss.h>
225 #include "gss_util.h"
226 #include "gss_oids.h"
227 #include "err_util.h"
228 diff -rNup nfs-utils-1.0.10/utils/gssd/context.h nfs-utils-1.0.10.lustre/utils/gssd/context.h
229 --- nfs-utils-1.0.10/utils/gssd/context.h 2007-05-15 13:02:26.000000000 -0600
230 +++ nfs-utils-1.0.10.lustre/utils/gssd/context.h 2007-05-15 13:01:35.000000000 -0600
235 -#include <rpc/rpc.h>
237 /* Hopefully big enough to hold any serialized context */
238 #define MAX_CTX_LEN 4096
240 diff -rNup nfs-utils-1.0.10/utils/gssd/context_lucid.c nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c
241 --- nfs-utils-1.0.10/utils/gssd/context_lucid.c 2007-05-15 13:02:26.000000000 -0600
242 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c 2007-05-15 13:01:35.000000000 -0600
247 -#include "gss_util.h"
248 -#include "gss_oids.h"
249 -#include "err_util.h"
250 -#include "context.h"
254 #include <gssapi/gssapi.h>
256 @@ -53,6 +49,11 @@ typedef uint64_t OM_uint64;
258 #include <gssapi/gssapi_krb5.h>
260 +#include "gss_util.h"
261 +#include "gss_oids.h"
262 +#include "err_util.h"
263 +#include "context.h"
266 write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
268 @@ -354,6 +355,7 @@ static int
269 prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
270 gss_buffer_desc *buf)
272 + static int constant_two = 2;
274 uint32_t v2_flags = 0;
275 gss_krb5_lucid_key_t enc_key;
276 @@ -372,7 +374,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
277 end = buf->value + MAX_CTX_LEN;
280 - if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
281 + if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
282 if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
285 @@ -434,14 +436,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
289 - if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
291 - KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
293 - if (write_bytes(&p, end, derived_key.data,
294 - derived_key.length))
296 - free(derived_key.data);
298 + * RC4 is special, it dosen't need key derivation. Actually
299 + * the Ke is based on plain text. Here we just let all three
300 + * key identical, kernel will handle everything. --ericm
302 + if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
303 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
304 + lctx->rfc1964_kd.ctx_key.length))
307 + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
309 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
311 + if (write_bytes(&p, end, derived_key.data,
312 + derived_key.length))
314 + free(derived_key.data);
317 gss_krb5_lucid_key_t *keyptr;
318 uint32_t sign_usage, seal_usage;
319 @@ -451,6 +464,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
321 keyptr = &lctx->cfx_kd.ctx_key;
324 if (lctx->initiate == 1) {
325 sign_usage = KG_USAGE_INITIATOR_SIGN;
326 seal_usage = KG_USAGE_INITIATOR_SEAL;
327 @@ -458,6 +472,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
328 sign_usage = KG_USAGE_ACCEPTOR_SIGN;
329 seal_usage = KG_USAGE_ACCEPTOR_SEAL;
333 + * These are from rfc4142, but I don't understand: if we supply
334 + * different 'usage' value for client & server, then the peers
335 + * will have different derived keys. How could this work?
337 + * Here we simply use old SIGN/SEAL values until we find the
341 + sign_usage = KG_USAGE_SIGN;
342 + seal_usage = KG_USAGE_SEAL;
345 /* derive and send down: Ke, Ki, and Kc */
347 diff -rNup nfs-utils-1.0.10/utils/gssd/context_mit.c nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c
348 --- nfs-utils-1.0.10/utils/gssd/context_mit.c 2007-05-15 13:02:26.000000000 -0600
349 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c 2007-05-15 13:01:35.000000000 -0600
352 #include <gssapi/gssapi.h>
354 -#include <rpc/auth_gss.h>
355 #include "gss_util.h"
356 #include "gss_oids.h"
357 #include "err_util.h"
358 @@ -333,12 +332,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
359 * keydata-2; ( Ki (Kseq for DES3) )
360 * keydata-3; ( Kc (derived checksum key) )
362 - if (kctx->initiate) {
363 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
366 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
368 + if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
369 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
371 /* Only applicable flag for this is initiator */
372 diff -rNup nfs-utils-1.0.10/utils/gssd/context_spkm3.c nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c
373 --- nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2007-05-15 13:02:26.000000000 -0600
374 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c 2007-05-15 13:01:35.000000000 -0600
378 #include <gssapi/gssapi.h>
379 -#include <rpc/rpc.h>
380 -#include <rpc/auth_gss.h>
381 #include "gss_util.h"
382 #include "gss_oids.h"
383 #include "err_util.h"
384 diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.c nfs-utils-1.0.10.lustre/utils/gssd/err_util.c
385 --- nfs-utils-1.0.10/utils/gssd/err_util.c 2006-08-07 00:40:50.000000000 -0600
386 +++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.c 2007-05-15 13:01:35.000000000 -0600
393 #include "err_util.h"
395 static int verbosity = 0;
396 @@ -91,3 +93,40 @@ printit:
397 /* reset the buffer */
398 memset(message_buf, 0, sizeof(message_buf));
401 +void print_hexl(int pri, unsigned char *cp, int length)
406 + printerr(pri, "length %d\n",length);
407 + printerr(pri, "\n");
409 + for (i = 0; i < length; i += 0x10) {
410 + printerr(pri, " %04x: ", (u_int)i);
412 + jm = jm > 16 ? 16 : jm;
414 + for (j = 0; j < jm; j++) {
416 + printerr(pri,"%02x ", (u_int)cp[i+j]);
418 + printerr(pri,"%02x", (u_int)cp[i+j]);
420 + for (; j < 16; j++) {
428 + for (j = 0; j < jm; j++) {
430 + c = isprint(c) ? c : '.';
431 + printerr(pri,"%c", c);
433 + printerr(pri,"\n");
437 diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.h nfs-utils-1.0.10.lustre/utils/gssd/err_util.h
438 --- nfs-utils-1.0.10/utils/gssd/err_util.h 2006-08-07 00:40:50.000000000 -0600
439 +++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.h 2007-05-15 13:01:35.000000000 -0600
442 void initerr(char *progname, int verbosity, int fg);
443 void printerr(int priority, char *format, ...);
444 +void print_hexl(int pri, unsigned char *cp, int length);
446 #endif /* _ERR_UTIL_H_ */
447 diff -rNup nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c
448 --- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c 2006-08-07 00:40:50.000000000 -0600
449 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c 2007-05-15 13:00:53.000000000 -0600
452 #include "write_bytes.h"
455 char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
458 @@ -102,3 +103,4 @@ main(int argc, char *argv[])
463 diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.c nfs-utils-1.0.10.lustre/utils/gssd/gssd.c
464 --- nfs-utils-1.0.10/utils/gssd/gssd.c 2007-05-15 13:02:26.000000000 -0600
465 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.c 2007-05-15 13:01:35.000000000 -0600
470 +#include <sys/types.h>
471 #include <sys/param.h>
472 #include <sys/socket.h>
473 -#include <rpc/rpc.h>
474 +#include <sys/wait.h>
475 +#include <sys/ipc.h>
476 +#include <sys/sem.h>
486 #include "err_util.h"
487 #include "gss_util.h"
488 #include "krb5_util.h"
489 +#include "lsupport.h"
491 char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
492 char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
493 char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
494 char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
495 int use_memcache = 0;
496 +int lgssd_mutex_downcall = -1;
500 +static int lgssd_create_mutex(int *semid)
505 + id = semget(IPC_PRIVATE, 1, IPC_CREAT);
507 + printerr(0, "semget: %s\n", strerror(errno));
512 + if (semctl(id, 0, SETVAL, arg) != 0) {
513 + printerr(0, "semctl: %s\n", strerror(errno));
514 + semctl(id, 1, IPC_RMID, arg);
522 +void lgssd_init_mutexs(void)
524 + if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
525 + printerr(0, "can't create downcall mutex\n");
530 +void lgssd_fini_mutexs(void)
534 + if (lgssd_mutex_downcall != -1)
535 + semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
538 +void lgssd_mutex_get(int semid)
540 + struct sembuf op[1] = { {0, -1, SEM_UNDO} };
543 + rc = semop(semid, op, 1);
545 + printerr(0, "exit on mutex_get err %d: %s\n",
546 + rc, strerror(errno));
551 +void lgssd_mutex_put(int semid)
553 + struct sembuf op[1] = { {0, 1, 0} };
556 + rc = semop(semid, op, 1);
558 + printerr(0, "ignore mutex_put err %d: %s\n",
559 + rc, strerror(errno));
563 +static void lgssd_cleanup(void)
567 + /* make sure all children finished */
569 + child_pid = waitpid(-1, NULL, 0);
573 + printerr(3, "cleanup: child %d terminated\n", child_pid);
576 + lgssd_fini_mutexs();
578 /* destroy krb5 machine creds */
579 gssd_destroy_krb5_machine_creds();
585 printerr(1, "exiting on signal %d\n", signal);
590 @@ -79,7 +166,7 @@ sig_hup(int signal)
592 usage(char *progname)
594 - fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
595 + fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
599 @@ -89,7 +176,6 @@ main(int argc, char *argv[])
603 - int rpc_verbosity = 0;
607 @@ -99,18 +185,12 @@ main(int argc, char *argv[])
612 - /* Accept but ignore this. Now the default. */
624 strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
625 if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
626 @@ -131,10 +211,6 @@ main(int argc, char *argv[])
630 - snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
631 - pipefs_dir, GSSD_SERVICE_NAME);
632 - if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
633 - errx(1, "pipefs_nfsdir path name too long");
635 if ((progname = strrchr(argv[0], '/')))
637 @@ -142,30 +218,42 @@ main(int argc, char *argv[])
640 initerr(progname, verbosity, fg);
641 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
642 - authgss_set_debug_level(rpc_verbosity);
644 - if (rpc_verbosity > 0)
645 - printerr(0, "Warning: rpcsec_gss library does not "
646 - "support setting debug level\n");
649 if (gssd_check_mechs() != 0)
650 errx(1, "Problem with gssapi library");
652 + if (gssd_get_local_realm())
653 + errx(1, "get local realm");
655 if (!fg && daemon(0, 0) < 0)
658 + /* This should be checked _after_ daemon(), because we need to own
659 + * the undo-able semaphore by this process
661 + gssd_init_unique(GSSD_CLI);
663 + /* Process keytab file and get machine credentials. This will modify
664 + * disk status so do it after we are sure we are the only instance
666 + if (gssd_refresh_krb5_machine_creds())
669 signal(SIGINT, sig_die);
670 signal(SIGTERM, sig_die);
671 signal(SIGHUP, sig_hup);
673 - /* Process keytab file and get machine credentials */
674 - gssd_refresh_krb5_machine_creds();
676 /* Determine Kerberos information from the kernel */
677 gssd_obtain_kernel_krb5_info();
680 + lgssd_init_mutexs();
682 + printerr(0, "lgssd initialized and ready to serve\n");
686 - printerr(0, "gssd_run returned!\n");
689 + printerr(0, "lgssd exiting\n");
692 diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.h nfs-utils-1.0.10.lustre/utils/gssd/gssd.h
693 --- nfs-utils-1.0.10/utils/gssd/gssd.h 2007-05-15 13:02:26.000000000 -0600
694 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.h 2007-05-15 13:01:35.000000000 -0600
696 #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_"
697 #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine"
698 #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
699 -#define GSSD_SERVICE_NAME "nfs"
700 -#define GSSD_SERVICE_NAME_LEN 3
701 +#define GSSD_SERVICE_MDS "lustre_mds"
702 +#define GSSD_SERVICE_OSS "lustre_oss"
703 +#define GSSD_SERVICE_MDS_NAMELEN 10
704 +#define GSSD_SERVICE_OSS_NAMELEN 10
706 +#define LUSTRE_ROOT_NAME "lustre_root"
707 +#define LUSTRE_ROOT_NAMELEN 11
710 * The gss mechanisms that we can handle
711 @@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
714 extern char pipefs_dir[PATH_MAX];
715 -extern char pipefs_nfsdir[PATH_MAX];
716 extern char keytabfile[PATH_MAX];
717 extern char ccachedir[PATH_MAX];
718 +extern char gethostname_ex[PATH_MAX];
719 extern int use_memcache;
721 TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
722 @@ -71,10 +76,6 @@ struct clnt_info {
733 @@ -85,8 +86,14 @@ void init_client_list(void);
734 int update_client_list(void);
735 void handle_krb5_upcall(struct clnt_info *clp);
736 void handle_spkm3_upcall(struct clnt_info *clp);
737 -int gssd_acquire_cred(char *server_name);
738 -void gssd_run(void);
739 +void lgssd_run(void);
742 +extern int lgssd_mutex_downcall;
744 +void lgssd_init_mutexs(void);
745 +void lgssd_fini_mutexs(void);
746 +void lgssd_mutex_get(int semid);
747 +void lgssd_mutex_put(int semid);
749 #endif /* _RPC_GSSD_H_ */
750 diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c
751 --- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c 2007-05-15 13:02:26.000000000 -0600
752 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c 2007-05-15 13:01:35.000000000 -0600
753 @@ -94,11 +94,13 @@ scan_poll_results(int ret)
761 struct sigaction dn_act;
763 + time_t child_check = 0;
766 /* Taken from linux/Documentation/dnotify.txt: */
767 dn_act.sa_sigaction = dir_notify_handler;
768 @@ -106,10 +108,10 @@ gssd_run()
769 dn_act.sa_flags = SA_SIGINFO;
770 sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
772 - if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
773 + if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
774 printerr(0, "ERROR: failed to open %s: %s\n",
775 - pipefs_nfsdir, strerror(errno));
777 + pipefs_dir, strerror(errno));
780 fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
781 fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
782 @@ -119,12 +121,30 @@ gssd_run()
784 while (dir_changed) {
786 + printerr(2, "pipefs root dir changed\n");
787 if (update_client_list()) {
788 printerr(0, "ERROR: couldn't update "
795 + /* every 5s cleanup possible zombies of child processes */
796 + if (time(NULL) - child_check >= 5) {
797 + printerr(3, "check zombie children...\n");
800 + child_pid = waitpid(-1, NULL, WNOHANG);
801 + if (child_pid <= 0)
804 + printerr(2, "terminate zombie child: %d\n",
808 + child_check = time(NULL);
811 /* race condition here: dir_changed could be set before we
812 * enter the poll, and we'd never notice if it weren't for the
814 @@ -139,6 +159,7 @@ gssd_run()
815 scan_poll_results(ret);
822 diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c
823 --- nfs-utils-1.0.10/utils/gssd/gssd_proc.c 2007-05-15 13:02:26.000000000 -0600
824 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c 2007-05-15 13:21:06.000000000 -0600
828 #include <sys/param.h>
829 -#include <rpc/rpc.h>
830 #include <sys/stat.h>
831 #include <sys/socket.h>
832 #include <arpa/inet.h>
834 #include "gss_oids.h"
835 #include "krb5_util.h"
837 +#include "lsupport.h"
841 @@ -99,86 +99,10 @@ struct pollfd * pollarray;
843 int pollsize; /* the size of pollaray (in pollfd's) */
845 -/* XXX buffer problems: */
847 -read_service_info(char *info_file_name, char **servicename, char **servername,
848 - int *prog, int *vers, char **protocol) {
849 -#define INFOBUFLEN 256
850 - char buf[INFOBUFLEN];
851 - static char dummy[128];
853 - static char service[128];
854 - static char address[128];
857 - char protoname[16];
860 - struct hostent *ent = NULL;
863 - *servicename = *servername = *protocol = NULL;
865 - if ((fd = open(info_file_name, O_RDONLY)) == -1) {
866 - printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
870 - if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
874 - numfields = sscanf(buf,"RPC server: %127s\n"
875 - "service: %127s %15s version %15s\n"
877 - "protocol: %15s\n",
879 - service, program, version,
883 - if (numfields == 5) {
884 - strcpy(protoname, "tcp");
885 - } else if (numfields != 6) {
889 - /* check service, program, and version */
890 - if(memcmp(service, "nfs", 3)) return -1;
891 - *prog = atoi(program + 1); /* skip open paren */
892 - *vers = atoi(version);
893 - if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
896 - /* create service name */
897 - inaddr = inet_addr(address);
898 - if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
899 - printerr(0, "ERROR: can't resolve server %s name\n", address);
902 - if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
904 - memcpy(*servername, ent->h_name, strlen(ent->h_name));
905 - snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
906 - if (!(*servicename = calloc(strlen(buf) + 1, 1)))
908 - memcpy(*servicename, buf, strlen(buf));
910 - if (!(*protocol = strdup(protoname)))
914 - printerr(0, "ERROR: failed to read service info\n");
915 - if (fd != -1) close(fd);
916 - if (*servername) free(*servername);
917 - if (*servicename) free(*servicename);
918 - if (*protocol) free(*protocol);
923 destroy_client(struct clnt_info *clp)
925 + printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
926 if (clp->krb5_poll_index != -1)
927 memset(&pollarray[clp->krb5_poll_index], 0,
928 sizeof(struct pollfd));
929 @@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
930 if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
931 if (clp->dirname) free(clp->dirname);
932 if (clp->servicename) free(clp->servicename);
933 - if (clp->servername) free(clp->servername);
934 - if (clp->protocol) free(clp->protocol);
938 @@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info
942 - char info_file_name[32];
944 if (clp->krb5_fd == -1) {
945 snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
946 @@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info
948 if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
950 - snprintf(info_file_name, sizeof(info_file_name), "%s/info",
952 - if ((clp->servicename == NULL) &&
953 - read_service_info(info_file_name, &clp->servicename,
954 - &clp->servername, &clp->prog, &clp->vers,
960 @@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
962 pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
963 pollarray[clp->krb5_poll_index].events |= POLLIN;
964 + printerr(2, "monitoring krb5 channel under %s\n",
968 if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
969 @@ -386,67 +302,106 @@ find_client(char *dirname)
971 update_client_list(void)
973 - struct dirent **namelist;
974 + char lustre_dir[PATH_MAX];
975 + struct dirent lustre_dirent = { .d_name = "lustre" };
976 + struct dirent *namelist[1];
977 + struct stat statbuf;
980 - if (chdir(pipefs_nfsdir) < 0) {
981 + if (chdir(pipefs_dir) < 0) {
982 printerr(0, "ERROR: can't chdir to %s: %s\n",
983 - pipefs_nfsdir, strerror(errno));
984 + pipefs_dir, strerror(errno));
988 - j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
990 - printerr(0, "ERROR: can't scandir %s: %s\n",
991 - pipefs_nfsdir, strerror(errno));
993 + snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
994 + if (stat(lustre_dir, &statbuf) == 0) {
995 + namelist[0] = &lustre_dirent;
997 + printerr(2, "re-processing lustre directory\n");
999 + namelist[0] = NULL;
1001 + printerr(2, "lustre directory not exist\n");
1004 update_old_clients(namelist, j);
1005 for (i=0; i < j; i++) {
1006 - if (i < FD_ALLOC_BLOCK
1007 - && !strncmp(namelist[i]->d_name, "clnt", 4)
1008 - && !find_client(namelist[i]->d_name))
1009 + if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
1010 process_clnt_dir(namelist[i]->d_name);
1011 - free(namelist[i]);
1019 +/* Context creation response. */
1020 +struct lustre_gss_init_res {
1021 + gss_buffer_desc gr_ctx; /* context handle */
1022 + u_int gr_major; /* major status */
1023 + u_int gr_minor; /* minor status */
1024 + u_int gr_win; /* sequence window */
1025 + gss_buffer_desc gr_token; /* token */
1028 +struct lustre_gss_data {
1029 + int lgd_established;
1030 + int lgd_lustre_svc; /* mds/oss */
1031 + int lgd_uid; /* uid */
1032 + char *lgd_uuid; /* client device uuid */
1033 + gss_name_t lgd_name; /* service name */
1035 + gss_OID lgd_mech; /* mech OID */
1036 + u_int lgd_req_flags; /* request flags */
1037 + gss_cred_id_t lgd_cred; /* credential */
1038 + gss_ctx_id_t lgd_ctx; /* session context */
1039 + gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */
1040 + uint32_t lgd_seq_win; /* sequence window */
1047 -do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
1048 - gss_buffer_desc *context_token)
1049 +do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
1050 + struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
1052 char *buf = NULL, *p = NULL, *end = NULL;
1053 unsigned int timeout = 0; /* XXX decide on a reasonable value */
1054 unsigned int buf_size = 0;
1056 - printerr(1, "doing downcall\n");
1057 - buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
1058 - sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
1059 + printerr(2, "doing downcall\n");
1060 + buf_size = sizeof(updata->seq) + sizeof(timeout) +
1061 + sizeof(lgd->lgd_seq_win) +
1062 + sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
1063 sizeof(context_token->length) + context_token->length;
1064 p = buf = malloc(buf_size);
1065 end = buf + buf_size;
1067 - if (WRITE_BYTES(&p, end, uid)) goto out_err;
1068 + if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
1069 /* Not setting any timeout for now: */
1070 if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1071 - if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
1072 - if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
1073 + if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
1074 + if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
1075 if (write_buffer(&p, end, context_token)) goto out_err;
1077 - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1078 + lgssd_mutex_get(lgssd_mutex_downcall);
1079 + if (write(k5_fd, buf, p - buf) < p - buf) {
1080 + lgssd_mutex_put(lgssd_mutex_downcall);
1083 + lgssd_mutex_put(lgssd_mutex_downcall);
1089 - printerr(0, "Failed to write downcall!\n");
1090 + printerr(0, "ERROR: Failed to write downcall!\n");
1095 -do_error_downcall(int k5_fd, uid_t uid, int err)
1096 +do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
1099 char *p = buf, *end = buf + 1024;
1100 @@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid,
1102 printerr(1, "doing error downcall\n");
1104 - if (WRITE_BYTES(&p, end, uid)) goto out_err;
1105 + if (WRITE_BYTES(&p, end, seq)) goto out_err;
1106 if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1107 /* use seq_win = 0 to indicate an error: */
1108 if (WRITE_BYTES(&p, end, zero)) goto out_err;
1109 - if (WRITE_BYTES(&p, end, err)) goto out_err;
1110 + if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
1111 + if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
1113 - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1114 + lgssd_mutex_get(lgssd_mutex_downcall);
1115 + if (write(k5_fd, buf, p - buf) < p - buf) {
1116 + lgssd_mutex_put(lgssd_mutex_downcall);
1119 + lgssd_mutex_put(lgssd_mutex_downcall);
1122 printerr(0, "Failed to write error downcall!\n");
1128 * Create an RPC connection and establish an authenticated
1129 * gss context with a server.
1130 @@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
1137 +int do_negotiation(struct lustre_gss_data *lgd,
1138 + gss_buffer_desc *gss_token,
1139 + struct lustre_gss_init_res *gr,
1142 + char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
1143 + struct lgssd_ioctl_param param;
1144 + struct passwd *pw;
1146 + char outbuf[8192];
1150 + pw = getpwuid(lgd->lgd_uid);
1152 + printerr(0, "no uid %u in local user database\n",
1157 + param.version = GSSD_INTERFACE_VERSION;
1158 + param.uuid = lgd->lgd_uuid;
1159 + param.lustre_svc = lgd->lgd_lustre_svc;
1160 + param.uid = lgd->lgd_uid;
1161 + param.gid = pw->pw_gid;
1162 + param.send_token_size = gss_token->length;
1163 + param.send_token = (char *) gss_token->value;
1164 + param.reply_buf_size = sizeof(outbuf);
1165 + param.reply_buf = outbuf;
1167 + fd = open(file, O_RDWR);
1169 + printerr(0, "can't open file %s\n", file);
1173 + ret = write(fd, ¶m, sizeof(param));
1175 + if (ret != sizeof(param)) {
1176 + printerr(0, "lustre ioctl err: %d\n", strerror(errno));
1180 + if (param.status) {
1182 + printerr(0, "status: %d (%s)\n",
1183 + param.status, strerror((int)param.status));
1184 + if (param.status == -ETIMEDOUT) {
1185 + /* kernel return -ETIMEDOUT means the rpc timedout,
1186 + * we should notify the caller to reinitiate the
1187 + * gss negotiation, by return -ERESTART
1189 + lgd->lgd_rpc_err = -ERESTART;
1190 + lgd->lgd_gss_err = 0;
1192 + lgd->lgd_rpc_err = param.status;
1193 + lgd->lgd_gss_err = 0;
1197 + p = (unsigned int *)outbuf;
1199 + gr->gr_major = *p++;
1200 + gr->gr_minor = *p++;
1201 + gr->gr_win = *p++;
1203 + gr->gr_ctx.length = *p++;
1204 + gr->gr_ctx.value = malloc(gr->gr_ctx.length);
1205 + memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
1206 + p += (((gr->gr_ctx.length + 3) & ~3) / 4);
1208 + gr->gr_token.length = *p++;
1209 + gr->gr_token.value = malloc(gr->gr_token.length);
1210 + memcpy(gr->gr_token.value, p, gr->gr_token.length);
1211 + p += (((gr->gr_token.length + 3) & ~3) / 4);
1213 + printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
1214 + gr->gr_ctx.length, gr->gr_token.length);
1220 +int gssd_refresh_lgd(struct lustre_gss_data *lgd)
1222 + struct lustre_gss_init_res gr;
1223 + gss_buffer_desc *recv_tokenp, send_token;
1224 + OM_uint32 maj_stat, min_stat, call_stat, ret_flags;
1226 + /* GSS context establishment loop. */
1227 + memset(&gr, 0, sizeof(gr));
1228 + recv_tokenp = GSS_C_NO_BUFFER;
1231 + /* print the token we just received */
1232 + if (recv_tokenp != GSS_C_NO_BUFFER) {
1233 + printerr(3, "The received token length %d\n",
1234 + recv_tokenp->length);
1235 + print_hexl(3, recv_tokenp->value, recv_tokenp->length);
1238 + maj_stat = gss_init_sec_context(&min_stat,
1243 + lgd->lgd_req_flags,
1245 + NULL, /* channel */
1247 + NULL, /* used mech */
1250 + NULL); /* time rec */
1252 + if (recv_tokenp != GSS_C_NO_BUFFER) {
1253 + gss_release_buffer(&min_stat, &gr.gr_token);
1254 + recv_tokenp = GSS_C_NO_BUFFER;
1256 + if (maj_stat != GSS_S_COMPLETE &&
1257 + maj_stat != GSS_S_CONTINUE_NEEDED) {
1258 + pgsserr("gss_init_sec_context", maj_stat, min_stat,
1262 + if (send_token.length != 0) {
1263 + memset(&gr, 0, sizeof(gr));
1265 + /* print the token we are about to send */
1266 + printerr(3, "token being sent length %d\n",
1267 + send_token.length);
1268 + print_hexl(3, send_token.value, send_token.length);
1270 + call_stat = do_negotiation(lgd, &send_token, &gr, 0);
1271 + gss_release_buffer(&min_stat, &send_token);
1273 + if (call_stat != 0 ||
1274 + (gr.gr_major != GSS_S_COMPLETE &&
1275 + gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
1276 + printerr(0, "call stat %d, major stat 0x%x\n",
1277 + (int)call_stat, gr.gr_major);
1281 + if (gr.gr_ctx.length != 0) {
1282 + if (lgd->lgd_rmt_ctx.value)
1283 + gss_release_buffer(&min_stat,
1284 + &lgd->lgd_rmt_ctx);
1285 + lgd->lgd_rmt_ctx = gr.gr_ctx;
1287 + if (gr.gr_token.length != 0) {
1288 + if (maj_stat != GSS_S_CONTINUE_NEEDED)
1290 + recv_tokenp = &gr.gr_token;
1294 + /* GSS_S_COMPLETE => check gss header verifier,
1295 + * usually checked in gss_validate
1297 + if (maj_stat == GSS_S_COMPLETE) {
1298 + lgd->lgd_established = 1;
1299 + lgd->lgd_seq_win = gr.gr_win;
1303 + /* End context negotiation loop. */
1304 + if (!lgd->lgd_established) {
1305 + if (gr.gr_token.length != 0)
1306 + gss_release_buffer(&min_stat, &gr.gr_token);
1308 + printerr(0, "context negotiation failed\n");
1312 + printerr(2, "successfully refreshed lgd\n");
1317 +int gssd_create_lgd(struct clnt_info *clp,
1318 + struct lustre_gss_data *lgd,
1319 + struct lgssd_upcall_data *updata,
1322 + gss_buffer_desc sname;
1323 + OM_uint32 maj_stat, min_stat;
1326 + lgd->lgd_established = 0;
1327 + lgd->lgd_lustre_svc = updata->svc;
1328 + lgd->lgd_uid = updata->uid;
1329 + lgd->lgd_uuid = updata->obd;
1331 + switch (authtype) {
1332 + case AUTHTYPE_KRB5:
1333 + lgd->lgd_mech = (gss_OID) &krb5oid;
1334 + lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1336 + case AUTHTYPE_SPKM3:
1337 + lgd->lgd_mech = (gss_OID) &spkm3oid;
1338 + /* XXX sec.req_flags = GSS_C_ANON_FLAG;
1339 + * Need a way to switch....
1341 + lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1344 + printerr(0, "Invalid authentication type (%d)\n", authtype);
1348 + lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
1349 + lgd->lgd_ctx = GSS_C_NO_CONTEXT;
1350 + lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
1351 + lgd->lgd_seq_win = 0;
1353 + sname.value = clp->servicename;
1354 + sname.length = strlen(clp->servicename);
1356 + maj_stat = gss_import_name(&min_stat, &sname,
1357 + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
1359 + if (maj_stat != GSS_S_COMPLETE) {
1360 + pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
1364 + retval = gssd_refresh_lgd(lgd);
1366 + if (lgd->lgd_name != GSS_C_NO_NAME)
1367 + gss_release_name(&min_stat, &lgd->lgd_name);
1369 + if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
1370 + gss_release_cred(&min_stat, &lgd->lgd_cred);
1377 +void gssd_free_lgd(struct lustre_gss_data *lgd)
1379 + gss_buffer_t token = GSS_C_NO_BUFFER;
1380 + OM_uint32 maj_stat, min_stat;
1382 + if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
1385 + maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
1389 +int construct_service_name(struct clnt_info *clp,
1390 + struct lgssd_upcall_data *ud)
1392 + const int buflen = 256;
1393 + char name[buflen];
1395 + if (clp->servicename) {
1396 + free(clp->servicename);
1397 + clp->servicename = NULL;
1400 + if (lnet_nid2hostname(ud->nid, name, buflen))
1403 + clp->servicename = malloc(32 + strlen(name));
1404 + if (!clp->servicename) {
1405 + printerr(0, "can't alloc memory\n");
1408 + sprintf(clp->servicename, "%s@%s",
1409 + ud->svc == LUSTRE_GSS_SVC_MDS ?
1410 + GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
1412 + printerr(2, "constructed servicename: %s\n", clp->servicename);
1417 * this code uses the userland rpcsec gss library to create a krb5
1418 @@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
1420 handle_krb5_upcall(struct clnt_info *clp)
1423 - CLIENT *rpc_clnt = NULL;
1424 - AUTH *auth = NULL;
1425 - struct authgss_private_data pd;
1426 - gss_buffer_desc token;
1428 + gss_buffer_desc token = { 0, NULL };
1429 + struct lgssd_upcall_data updata;
1430 + struct lustre_gss_data lgd;
1431 char **credlist = NULL;
1435 - printerr(1, "handling krb5 upcall\n");
1436 + printerr(2, "handling krb5 upcall\n");
1439 - token.value = NULL;
1440 - memset(&pd, 0, sizeof(struct authgss_private_data));
1441 + memset(&lgd, 0, sizeof(lgd));
1442 + lgd.lgd_rpc_err = -EPERM; /* default error code */
1444 - if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
1445 - printerr(0, "WARNING: failed reading uid from krb5 "
1446 + read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
1447 + if (read_rc < 0) {
1448 + printerr(0, "WARNING: failed reading from krb5 "
1449 "upcall pipe: %s\n", strerror(errno));
1452 + } else if (read_rc != sizeof(updata)) {
1453 + printerr(0, "upcall data mismatch: length %d, expect %d\n",
1454 + read_rc, sizeof(updata));
1456 + /* the sequence number must be the first field. if read >= 4
1457 + * bytes then we know at least sequence is fine, try to send
1458 + * error notification nicely.
1461 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1465 + /* FIXME temporary fix, do this before fork.
1466 + * in case of errors could have memory leak!!!
1468 + if (updata.uid == 0) {
1469 + if (gssd_get_krb5_machine_cred_list(&credlist)) {
1470 + printerr(0, "ERROR: Failed to obtain machine "
1472 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1477 + /* fork child process */
1480 + printerr(0, "can't fork: %s\n", strerror(errno));
1481 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1483 + } else if (pid > 0) {
1484 + printerr(2, "forked child process: %d\n", pid);
1488 + printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
1489 + updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
1491 + if (updata.svc != LUSTRE_GSS_SVC_MDS &&
1492 + updata.svc != LUSTRE_GSS_SVC_OSS) {
1493 + printerr(0, "invalid svc %d\n", updata.svc);
1494 + lgd.lgd_rpc_err = -EPROTO;
1495 + goto out_return_error;
1497 + updata.obd[sizeof(updata.obd)-1] = '\0';
1499 + if (construct_service_name(clp, &updata)) {
1500 + printerr(0, "failed to construct service name\n");
1501 + goto out_return_error;
1505 + if (updata.uid == 0) {
1509 * Get a list of credential cache names and try each
1510 * of them until one works or we've tried them all
1513 if (gssd_get_krb5_machine_cred_list(&credlist)) {
1514 - printerr(0, "WARNING: Failed to obtain machine "
1515 - "credentials for connection to "
1516 - "server %s\n", clp->servername);
1517 - goto out_return_error;
1518 + printerr(0, "ERROR: Failed to obtain machine "
1519 + "credentials for %s\n", clp->servicename);
1520 + goto out_return_error;
1523 for (ccname = credlist; ccname && *ccname; ccname++) {
1524 gssd_setup_krb5_machine_gss_ccache(*ccname);
1525 - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1526 - AUTHTYPE_KRB5)) == 0) {
1527 + if ((gssd_create_lgd(clp, &lgd, &updata,
1528 + AUTHTYPE_KRB5)) == 0) {
1533 printerr(2, "WARNING: Failed to create krb5 context "
1534 "for user with uid %d with credentials "
1535 - "cache %s for server %s\n",
1536 - uid, *ccname, clp->servername);
1537 + "cache %s for service %s\n",
1538 + updata.uid, *ccname, clp->servicename);
1540 gssd_free_krb5_machine_cred_list(credlist);
1542 - printerr(0, "WARNING: Failed to create krb5 context "
1543 + printerr(0, "ERROR: Failed to create krb5 context "
1544 "for user with uid %d with any "
1545 - "credentials cache for server %s\n",
1546 - uid, clp->servername);
1547 + "credentials cache for service %s\n",
1548 + updata.uid, clp->servicename);
1549 goto out_return_error;
1553 /* Tell krb5 gss which credentials cache to use */
1554 - gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
1555 + gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
1557 - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1558 - AUTHTYPE_KRB5)) != 0) {
1559 + if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
1560 printerr(0, "WARNING: Failed to create krb5 context "
1561 - "for user with uid %d for server %s\n",
1562 - uid, clp->servername);
1563 + "for user with uid %d for service %s\n",
1564 + updata.uid, clp->servicename);
1565 goto out_return_error;
1569 - if (!authgss_get_private_data(auth, &pd)) {
1570 - printerr(0, "WARNING: Failed to obtain authentication "
1571 - "data for user with uid %d for server %s\n",
1572 - uid, clp->servername);
1573 - goto out_return_error;
1576 - if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
1577 + if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
1578 printerr(0, "WARNING: Failed to serialize krb5 context for "
1579 - "user with uid %d for server %s\n",
1580 - uid, clp->servername);
1581 + "user with uid %d for service %s\n",
1582 + updata.uid, clp->servicename);
1583 goto out_return_error;
1586 - do_downcall(clp->krb5_fd, uid, &pd, &token);
1587 + printerr(1, "refreshed: %u@%s for %s\n",
1588 + updata.uid, updata.obd, clp->servicename);
1589 + do_downcall(clp->krb5_fd, &updata, &lgd, &token);
1594 - if (pd.pd_ctx_hndl.length != 0)
1595 - authgss_free_private_data(&pd);
1597 - AUTH_DESTROY(auth);
1599 - clnt_destroy(rpc_clnt);
1602 + gssd_free_lgd(&lgd);
1603 + exit(0); /* i'm child process */
1606 - do_error_downcall(clp->krb5_fd, uid, -1);
1607 + do_error_downcall(clp->krb5_fd, updata.seq,
1608 + lgd.lgd_rpc_err, lgd.lgd_gss_err);
1612 @@ -775,6 +1059,7 @@ out_return_error:
1614 handle_spkm3_upcall(struct clnt_info *clp)
1618 CLIENT *rpc_clnt = NULL;
1620 @@ -826,4 +1111,5 @@ out:
1622 do_error_downcall(clp->spkm3_fd, uid, -1);
1626 diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.c nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c
1627 --- nfs-utils-1.0.10/utils/gssd/gss_util.c 2006-08-07 00:40:50.000000000 -0600
1628 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c 2007-05-15 13:01:35.000000000 -0600
1630 #ifdef HAVE_COM_ERR_H
1631 #include <com_err.h>
1633 +#include "lsupport.h"
1635 /* Global gssd_credentials handle */
1636 -gss_cred_id_t gssd_creds;
1637 +gss_cred_id_t gssd_cred_mds;
1638 +gss_cred_id_t gssd_cred_oss;
1639 +int gssd_cred_mds_valid = 0;
1640 +int gssd_cred_oss_valid = 0;
1642 +char *mds_local_realm = NULL;
1643 +char *oss_local_realm = NULL;
1645 gss_OID g_mechOid = GSS_C_NULL_OID;;
1647 @@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
1648 display_status_2(msg, maj_stat, min_stat, mech);
1652 -gssd_acquire_cred(char *server_name)
1654 +int extract_realm_name(gss_buffer_desc *name, char **realm)
1659 + sname = malloc(name->length + 1);
1661 + printerr(0, "out of memory\n");
1665 + memcpy(sname, name->value, name->length);
1666 + sname[name->length] = '\0';
1667 + printerr(1, "service principal: %s\n", sname);
1669 + c = strchr(sname, '@');
1671 + printerr(2, "no realm found in principal, use default\n");
1672 + *realm = strdup(this_realm);
1674 + printerr(0, "failed to duplicate default realm\n");
1679 + *realm = strdup(c);
1681 + printerr(0, "failed to duplicated realm\n");
1691 +int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
1692 + char **local_realm, int *valid)
1694 gss_buffer_desc name;
1695 gss_name_t target_name;
1696 u_int32_t maj_stat, min_stat;
1697 u_int32_t ignore_maj_stat, ignore_min_stat;
1698 + gss_OID name_type;
1699 gss_buffer_desc pbuf;
1703 name.value = (void *)server_name;
1704 name.length = strlen(server_name);
1706 @@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
1708 if (maj_stat != GSS_S_COMPLETE) {
1709 pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
1714 + maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
1715 + if (maj_stat != GSS_S_COMPLETE) {
1716 + pgsserr(0, maj_stat, min_stat, g_mechOid);
1719 + if (extract_realm_name(&name, local_realm))
1722 maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
1723 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
1724 - &gssd_creds, NULL, NULL);
1725 + cred, NULL, NULL);
1727 if (maj_stat != GSS_S_COMPLETE) {
1728 pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
1729 @@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
1730 ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
1737 ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
1739 - return (maj_stat == GSS_S_COMPLETE);
1740 + if (maj_stat != GSS_S_COMPLETE)
1745 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
1747 + if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
1748 + &mds_local_realm, &gssd_cred_mds_valid)) {
1753 + if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
1754 + &oss_local_realm, &gssd_cred_oss_valid)) {
1759 + if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
1760 + printerr(0, "can't obtain both mds & oss creds, exit\n");
1764 + if (gssd_cred_mds_valid)
1765 + printerr(0, "Ready to serve Lustre MDS in realm %s\n",
1766 + mds_local_realm ? mds_local_realm : "N/A");
1767 + if (gssd_cred_oss_valid)
1768 + printerr(0, "Ready to serve Lustre OSS in realm %s\n",
1769 + oss_local_realm ? oss_local_realm : "N/A");
1774 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
1776 + switch (lustre_svc) {
1777 + case LUSTRE_GSS_SVC_MDS:
1778 + if (!gssd_cred_mds_valid) {
1779 + printerr(0, "ERROR: service cred for mds not ready\n");
1782 + printerr(2, "select mds service cred\n");
1783 + return gssd_cred_mds;
1784 + case LUSTRE_GSS_SVC_OSS:
1785 + if (!gssd_cred_oss_valid) {
1786 + printerr(0, "ERROR: service cred for oss not ready\n");
1789 + printerr(2, "select oss service cred\n");
1790 + return gssd_cred_oss;
1792 + printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
1798 int gssd_check_mechs(void)
1799 @@ -249,3 +361,42 @@ out:
1803 +/*********************************
1804 + * FIXME should be in krb5_util.c
1805 + *********************************/
1807 +#include "krb5_util.h"
1809 +/* realm of this node */
1810 +char *this_realm = NULL;
1812 +int gssd_get_local_realm(void)
1814 + krb5_context context = NULL;
1815 + krb5_error_code code;
1818 + if (this_realm != NULL)
1821 + code = krb5_init_context(&context);
1823 + printerr(0, "ERROR: get default realm: init ctx: %s\n",
1824 + error_message(code));
1828 + code = krb5_get_default_realm(context, &this_realm);
1830 + printerr(0, "ERROR: get default realm: %s\n",
1831 + error_message(code));
1836 + printerr(1, "Local realm: %s\n", this_realm);
1838 + krb5_free_context(context);
1842 diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.h nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h
1843 --- nfs-utils-1.0.10/utils/gssd/gss_util.h 2006-08-07 00:40:50.000000000 -0600
1844 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h 2007-05-15 13:01:35.000000000 -0600
1846 #define _GSS_UTIL_H_
1849 -#include <rpc/rpc.h>
1850 #include "write_bytes.h"
1853 extern gss_cred_id_t gssd_creds;
1855 -int gssd_acquire_cred(char *server_name);
1856 void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
1857 const gss_OID mech);
1858 int gssd_check_mechs(void);
1859 +int gssd_get_local_realm(void);
1861 #endif /* _GSS_UTIL_H_ */
1862 diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.c nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c
1863 --- nfs-utils-1.0.10/utils/gssd/krb5_util.c 2007-05-15 13:02:26.000000000 -0600
1864 +++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c 2007-05-15 13:01:35.000000000 -0600
1866 #include <rpc/rpc.h>
1867 #include <sys/types.h>
1868 #include <sys/stat.h>
1869 +#include <sys/utsname.h>
1870 #include <sys/socket.h>
1871 #include <arpa/inet.h>
1873 +#include <unistd.h>
1882 #include <gssapi/gssapi_krb5.h>
1885 -#include <rpc/auth_gss.h>
1888 #include "err_util.h"
1889 @@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
1890 int num_krb5_enctypes = 0;
1891 krb5_enctype *krb5_enctypes = NULL;
1893 +/* credential expire time in advance */
1894 +unsigned long machine_cred_expire_advance = 300; /* 5 mins */
1896 /*==========================*/
1897 /*=== Internal routines ===*/
1898 /*==========================*/
1899 @@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
1900 static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
1901 static int gssd_get_single_krb5_cred(krb5_context context,
1902 krb5_keytab kt, struct gssd_k5_kt_princ *ple);
1903 -static int gssd_have_realm_ple(void *realm);
1904 static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
1908 + * convenient macros, these perhaps need further cleanup
1912 +#define KEYTAB_ENTRY_MATCH(kte, name) \
1914 + (kte).principal->data[0].length == (sizeof(name)-1) && \
1915 + strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0 \
1917 +#define KRB5_FREE_UNPARSED_NAME(ctx, name) \
1918 + krb5_free_unparsed_name((ctx), (name));
1919 +#define KRB5_STRDUP(str) \
1920 + strndup((str).data, (str).length)
1921 +#define KRB5_STRCMP(str, name) \
1923 + (str)->length != strlen(name) || \
1924 + strncmp((str)->data, (name), (str)->length) != 0 \
1926 +#define KRB5_STRCASECMP(str, name) \
1928 + (str)->length != strlen(name) || \
1929 + strncasecmp((str)->data, (name), (str)->length) != 0 \
1932 +#else /* !HAVE_KRB5 */
1934 +#define KEYTAB_ENTRY_MATCH(kte, name) \
1936 + strlen((kte).principal->name.name_string.val[0]) == \
1937 + (sizeof(name)-1) && \
1938 + strncmp(kte.principal->name.name_string.val[0], (name), \
1939 + sizeof(name)-1) == 0 \
1941 +#define KRB5_FREE_UNPARSED_NAME(ctx, name) \
1943 +#define KRB5_STRDUP(str) \
1945 +#define KRB5_STRCMP(str, name) \
1946 + strcmp((str), (name))
1947 +#define KRB5_STRCASECMP(str, name) \
1948 + strcmp((str), (name))
1950 +#endif /* HAVE_KRB5 */
1953 * Called from the scandir function to weed out potential krb5
1954 * credentials cache files
1956 @@ -294,7 +343,7 @@ gssd_get_single_krb5_cred(krb5_context c
1958 memset(&my_creds, 0, sizeof(my_creds));
1960 - if (ple->ccname && ple->endtime > now) {
1961 + if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
1962 printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
1963 ple->ccname, ple->endtime);
1965 @@ -314,6 +363,12 @@ gssd_get_single_krb5_cred(krb5_context c
1966 /* set a short lifetime (for debugging only!) */
1967 printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
1968 krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
1970 + /* FIXME try to get the ticket with lifetime as long as possible,
1971 + * to work around ticket-expiry + recovery problem in cmd3-11
1974 + krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
1976 if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
1977 kt, 0, NULL, &options))) {
1978 @@ -325,11 +380,7 @@ gssd_get_single_krb5_cred(krb5_context c
1979 "principal '%s' from keytab '%s'\n",
1980 error_message(code),
1981 pname ? pname : "<unparsable>", kt_name);
1983 - if (pname) krb5_free_unparsed_name(context, pname);
1985 - if (pname) free(pname);
1987 + if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
1991 @@ -378,15 +429,7 @@ gssd_get_single_krb5_cred(krb5_context c
1996 - * Determine if we already have a ple for the given realm
1999 - * 0 => no ple found for given realm
2000 - * 1 => found ple for given realm
2003 -gssd_have_realm_ple(void *r)
2004 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
2006 struct gssd_k5_kt_princ *ple;
2008 @@ -396,18 +439,76 @@ gssd_have_realm_ple(void *r)
2011 for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
2013 - if ((realm->length == strlen(ple->realm)) &&
2014 - (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2016 - if (strcmp(realm, ple->realm) == 0) {
2020 + if (KRB5_STRCMP(realm, ple->realm) == 0)
2026 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2029 + krb5_free_principal(kctx, ple->princ);
2033 + free(ple->ccname);
2037 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2039 + struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2040 + struct gssd_k5_kt_princ *ent = gssd_k5_kt_princ_list;
2042 + for (; ent; prev = &ent->next, ent = ent->next) {
2046 + *prev = ent->next;
2047 + gssd_free_ple(kctx, ent);
2054 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2055 + krb5_principal principal)
2057 + struct gssd_k5_kt_princ *ple;
2058 + krb5_error_code code;
2060 + ple = malloc(sizeof(*ple));
2061 + if (ple == NULL) {
2062 + printerr(0, "ERROR: could not allocate storage "
2063 + "for principal list entry\n");
2067 + memset(ple, 0, sizeof(*ple));
2069 + ple->realm = KRB5_STRDUP(principal->realm);
2070 + if (ple->realm == NULL) {
2071 + printerr(0, "ERROR: not enough memory while copying realm to "
2072 + "principal list entry\n");
2076 + code = krb5_copy_principal(kctx, principal, &ple->princ);
2078 + printerr(0, "ERROR: %s while copying principal "
2079 + "to principal list entry\n",
2080 + error_message(code));
2086 + gssd_free_ple(kctx, ple);
2091 * Process the given keytab file and create a list of principals we
2092 * might use to perform mount operations.
2093 @@ -451,82 +552,106 @@ gssd_process_krb5_keytab(krb5_context co
2095 printerr(2, "Processing keytab entry for principal '%s'\n",
2098 - if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
2099 - (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
2100 - GSSD_SERVICE_NAME_LEN) == 0) &&
2102 - if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
2103 - (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
2104 - GSSD_SERVICE_NAME_LEN) == 0) &&
2107 - (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
2108 - printerr(2, "We will use this entry (%s)\n", pname);
2109 - ple = malloc(sizeof(struct gssd_k5_kt_princ));
2110 - if (ple == NULL) {
2111 - printerr(0, "ERROR: could not allocate storage "
2112 - "for principal list entry\n");
2114 - krb5_free_unparsed_name(context, pname);
2121 + /* mds service entry:
2122 + * - hostname and realm should match this node
2123 + * - replace existing non-mds entry of this realm
2125 + if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
2126 + krb5_principal princ = kte.principal;
2127 + krb5_data *princ_host;
2128 + struct utsname utsbuf;
2129 + struct hostent *host;
2131 + if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2132 + this_realm) != 0) {
2133 + printerr(2, "alien mds service entry, skip\n");
2136 - /* These will be filled in later */
2138 - ple->ccname = NULL;
2142 - strndup(kte.principal->realm.data,
2143 - kte.principal->realm.length))
2145 - strdup(kte.principal->realm))
2148 - printerr(0, "ERROR: %s while copying realm to "
2149 - "principal list entry\n",
2150 - "not enough memory");
2152 - krb5_free_unparsed_name(context, pname);
2159 + princ_host = krb5_princ_component(context, princ, 1);
2160 + if (princ_host == NULL) {
2161 + printerr(2, "mds service entry: no hostname in "
2162 + "principal, skip\n");
2165 - if ((code = krb5_copy_principal(context,
2166 - kte.principal, &ple->princ))) {
2167 - printerr(0, "ERROR: %s while copying principal "
2168 - "to principal list entry\n",
2169 - error_message(code));
2171 - krb5_free_unparsed_name(context, pname);
2178 + if (uname(&utsbuf)) {
2179 + printerr(2, "mds service entry: unable to get "
2180 + "UTS name, skip\n");
2183 - if (gssd_k5_kt_princ_list == NULL)
2184 - gssd_k5_kt_princ_list = ple;
2186 - ple->next = gssd_k5_kt_princ_list;
2187 - gssd_k5_kt_princ_list = ple;
2188 + host = gethostbyname(utsbuf.nodename);
2189 + if (host == NULL) {
2190 + printerr(2, "mds service entry: unable to get "
2191 + "local hostname, skip\n");
2197 + if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
2198 + printerr(2, "mds service entry: hostname "
2199 + "doesn't match: %s - %.*s, skip\n",
2201 + princ_host->length, princ_host->data);
2205 + ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2207 + if (ple->fl_mds) {
2208 + printerr(2,"mds service entry: found a"
2209 + "duplicated one, it's like a "
2210 + "mis-configuration, skip\n");
2214 + gssd_remove_ple(context, ple);
2215 + printerr(2, "mds service entry: replace an "
2216 + "existed non-mds one\n");
2218 + } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2219 + ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2221 + if (ple->fl_mds || ple->fl_root) {
2222 + printerr(2, "root entry: found a "
2223 + "existed %s entry, skip\n",
2224 + ple->fl_mds ? "mds" : "root");
2228 + gssd_remove_ple(context, ple);
2229 + printerr(2, "root entry: replace an existed "
2230 + "non-mds non-root one\n");
2233 printerr(2, "We will NOT use this entry (%s)\n",
2238 - krb5_free_unparsed_name(context, pname);
2243 + /* construct ple */
2244 + printerr(2, "We will use this entry (%s)\n", pname);
2245 + ple = gssd_create_ple(context, kte.principal);
2246 + if (ple == NULL) {
2247 + KRB5_FREE_UNPARSED_NAME(context, pname);
2251 + /* add proper flags */
2252 + if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2254 + else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2258 + if (gssd_k5_kt_princ_list == NULL)
2259 + gssd_k5_kt_princ_list = ple;
2261 + ple->next = gssd_k5_kt_princ_list;
2262 + gssd_k5_kt_princ_list = ple;
2265 + KRB5_FREE_UNPARSED_NAME(context, pname);
2268 if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
2269 @@ -642,6 +767,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
2270 printerr(2, "getting credentials for client with uid %u for "
2271 "server %s\n", uid, servername);
2272 memset(buf, 0, sizeof(buf));
2274 if (gssd_find_existing_krb5_ccache(uid, &d)) {
2275 snprintf(buf, sizeof(buf), "FILE:%s/%s",
2276 ccachedir, d->d_name);
2277 @@ -702,7 +828,7 @@ gssd_refresh_krb5_machine_creds(void)
2281 - printerr(1, "Using keytab file '%s'\n", keytabfile);
2282 + printerr(2, "Using keytab file '%s'\n", keytabfile);
2284 if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
2285 printerr(0, "ERROR: %s while resolving keytab '%s'\n",
2286 @@ -717,12 +843,12 @@ gssd_refresh_krb5_machine_creds(void)
2287 if (gssd_k5_kt_princ_list == NULL) {
2288 printerr(0, "ERROR: No usable keytab entries found in "
2289 "keytab '%s'\n", keytabfile);
2290 - printerr(0, "Do you have a valid keytab entry for "
2291 - "%s/<your.host>@<YOUR.REALM> in "
2292 + printerr(0, "You must have a valid keytab entry for "
2293 + "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
2294 + "and %s@<YOUR.REALM> on client nodes, in "
2295 "keytab file %s ?\n",
2296 - GSSD_SERVICE_NAME, keytabfile);
2297 - printerr(0, "Continuing without (machine) credentials "
2298 - "- nfs4 mounts with Kerberos will fail\n");
2299 + GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
2304 @@ -872,6 +998,7 @@ gssd_destroy_krb5_machine_creds(void)
2305 krb5_free_context(context);
2309 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2311 * this routine obtains a credentials handle via gss_acquire_cred()
2312 @@ -927,6 +1054,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2315 #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2319 * Obtain supported enctypes from kernel.
2320 diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.h nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h
2321 --- nfs-utils-1.0.10/utils/gssd/krb5_util.h 2007-05-15 13:02:26.000000000 -0600
2322 +++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h 2007-05-15 13:01:35.000000000 -0600
2324 struct gssd_k5_kt_princ {
2325 struct gssd_k5_kt_princ *next;
2326 krb5_principal princ;
2327 + unsigned int fl_root:1,
2331 krb5_timestamp endtime;
2332 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2333 void gssd_obtain_kernel_krb5_info(void);
2336 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2337 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2340 #endif /* KRB5_UTIL_H */
2341 diff -rNup nfs-utils-1.0.10/utils/gssd/lgss_keyring.c nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c
2342 --- nfs-utils-1.0.10/utils/gssd/lgss_keyring.c 1969-12-31 17:00:00.000000000 -0700
2343 +++ nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c 2007-05-15 13:01:35.000000000 -0600
2346 + * lucall_keyring.c
2347 + * user-space upcall to create GSS context, using keyring interface to kernel
2349 + * Copyright (c) 2007 Cluster File Systems, Inc.
2350 + * Author: Eric Mei <ericm@clusterfs.com>
2352 + * This file is part of the Lustre file system, http://www.lustre.org
2353 + * Lustre is a trademark of Cluster File Systems, Inc.
2355 + * You may have signed or agreed to another license before downloading
2356 + * this software. If so, you are bound by the terms and conditions
2357 + * of that agreement, and the following does not apply to you. See the
2358 + * LICENSE file included with this distribution for more information.
2360 + * If you did not agree to a different license, then this copy of Lustre
2361 + * is open source software; you can redistribute it and/or modify it
2362 + * under the terms of version 2 of the GNU General Public License as
2363 + * published by the Free Software Foundation.
2365 + * In either case, Lustre is distributed in the hope that it will be
2366 + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
2367 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2368 + * license text for more details.
2371 +#include <unistd.h>
2372 +#include <stdlib.h>
2375 +#include <string.h>
2377 +#include <stdarg.h>
2378 +#include <syslog.h>
2379 +#include <assert.h>
2381 +#include <keyutils.h>
2382 +#include <gssapi/gssapi.h>
2384 +#include <libcfs/libcfs.h>
2386 +#include "lsupport.h"
2387 +#include "write_bytes.h"
2388 +#include "krb5_util.h"
2389 +#include "gss_oids.h"
2390 +#include "context.h"
2393 + * XXX TEMP to satisfy link. should be removed!!!
2395 +char ccachedir[PATH_MAX] = "/tmp";
2396 +char keytabfile[PATH_MAX] = "/etc/krb5.keytab";
2397 +int use_memcache = 0;
2399 +/****************************************
2400 + * log facilities *
2401 + ****************************************/
2405 + * 0: critical error messages
2406 + * 1: warning included
2408 + * 3: excessive messages
2417 +loglevel_t g_log_level = LL_TRACE;
2419 +static void logmsg(loglevel_t level, const char *format, ...)
2425 + if (level > g_log_level)
2428 + offset = snprintf(buf, sizeof(buf), "[%d]: ", getpid());
2430 + va_start(ap, format);
2431 + vsnprintf(buf + offset, sizeof(buf) - offset, format, ap);
2434 + syslog(LOG_INFO, "%s", buf);
2437 +static void logmsg_gss(loglevel_t level, const gss_OID mech,
2438 + u_int32_t major, u_int32_t minor,
2439 + const char *format, ...)
2442 + u_int32_t maj_stat1, min_stat1;
2443 + u_int32_t maj_stat2, min_stat2;
2444 + gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER;
2445 + gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER;
2446 + char maj_buf[30], min_buf[30];
2448 + uint32_t msg_ctx = 0;
2450 + if (level > g_log_level)
2453 + /* Get major status message */
2454 + maj_stat1 = gss_display_status(&min_stat1, major,
2455 + GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf);
2457 + if (maj_stat1 != GSS_S_COMPLETE) {
2458 + snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major);
2459 + maj = &maj_buf[0];
2461 + maj = maj_gss_buf.value;
2464 + /* Get minor status message */
2465 + maj_stat2 = gss_display_status(&min_stat2, minor,
2466 + GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf);
2468 + if (maj_stat2 != GSS_S_COMPLETE) {
2469 + snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor);
2470 + min = &min_buf[0];
2472 + min = min_gss_buf.value;
2475 + syslog(LOG_INFO, "GSS-API: %s - %s\n", maj, min);
2477 + va_start(ap, format);
2478 + vsyslog(LOG_INFO, format, ap);
2481 + if (maj_gss_buf.length != 0)
2482 + (void) gss_release_buffer(&min_stat1, &maj_gss_buf);
2483 + if (min_gss_buf.length != 0)
2484 + (void) gss_release_buffer(&min_stat2, &min_gss_buf);
2487 +#define lassert(exp) \
2489 + if ((int)(exp) == 0) { \
2490 + logmsg(LL_ERR, "ASSERTION FAILED: #exp"); \
2495 +/****************************************
2496 + * global declaration *
2497 + ****************************************/
2505 +const char *lgss_svc_name[LGSS_SVC_MAX] = {
2506 + [LGSS_SVC_MDS] = "lustre_mds",
2507 + [LGSS_SVC_OSS] = "lustre_oss",
2515 + * all data about negotiation
2517 +struct lgss_nego_data {
2518 + uint32_t lnd_established:1;
2520 + uint32_t lnd_lsvc;
2523 + gss_OID lnd_mech; /* mech OID */
2524 + gss_name_t lnd_svc_name; /* service name */
2525 + u_int lnd_req_flags; /* request flags */
2526 + gss_cred_id_t lnd_cred; /* credential */
2527 + gss_ctx_id_t lnd_ctx; /* session context */
2528 + gss_buffer_desc lnd_rmt_ctx; /* remote handle of context */
2529 + uint32_t lnd_seq_win; /* sequence window */
2536 + * context creation response
2538 +struct lgss_init_res {
2539 + gss_buffer_desc gr_ctx; /* context handle */
2540 + u_int gr_major; /* major status */
2541 + u_int gr_minor; /* minor status */
2542 + u_int gr_win; /* sequence window */
2543 + gss_buffer_desc gr_token; /* token */
2546 +struct keyring_upcall_param {
2556 + * gss target string of lustre service we are negotiating for
2558 +char *g_service = NULL;
2560 +/****************************************
2561 + * child process: gss negotiation *
2562 + ****************************************/
2564 +#define INIT_CHANNEL "/proc/fs/lustre/sptlrpc/gss/init_channel"
2566 +int do_nego_rpc(struct lgss_nego_data *lnd,
2567 + gss_buffer_desc *gss_token,
2568 + struct lgss_init_res *gr)
2570 + struct lgssd_ioctl_param param;
2571 + struct passwd *pw;
2573 + char outbuf[8192];
2576 + logmsg(LL_TRACE, "do_nego_rpc: get started\n");
2578 + pw = getpwuid(lnd->lnd_uid);
2580 + logmsg(LL_ERR, "no uid %u in local user database\n",
2585 + param.version = GSSD_INTERFACE_VERSION;
2586 + param.uuid = lnd->lnd_uuid;
2587 + param.lustre_svc = lnd->lnd_lsvc;
2588 + param.uid = lnd->lnd_uid;
2589 + param.gid = pw->pw_gid;
2590 + param.send_token_size = gss_token->length;
2591 + param.send_token = (char *) gss_token->value;
2592 + param.reply_buf_size = sizeof(outbuf);
2593 + param.reply_buf = outbuf;
2595 + logmsg(LL_TRACE, "to open " INIT_CHANNEL "\n");
2597 + fd = open(INIT_CHANNEL, O_WRONLY);
2599 + logmsg(LL_ERR, "can't open " INIT_CHANNEL "\n");
2603 + logmsg(LL_TRACE, "to down-write\n");
2605 + ret = write(fd, ¶m, sizeof(param));
2606 + if (ret != sizeof(param)) {
2607 + logmsg(LL_ERR, "lustre ioctl err: %d\n", strerror(errno));
2613 + logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n");
2614 + if (param.status) {
2615 + logmsg(LL_ERR, "status: %d (%s)\n",
2616 + param.status, strerror((int)param.status));
2618 + if (param.status == -ETIMEDOUT) {
2619 + /* kernel return -ETIMEDOUT means the rpc timedout,
2620 + * we should notify the caller to reinitiate the
2621 + * gss negotiation, by return -ERESTART
2623 + lnd->lnd_rpc_err = -ERESTART;
2624 + lnd->lnd_gss_err = 0;
2626 + lnd->lnd_rpc_err = param.status;
2627 + lnd->lnd_gss_err = 0;
2633 + p = (unsigned int *)outbuf;
2635 + gr->gr_major = *p++;
2636 + gr->gr_minor = *p++;
2637 + gr->gr_win = *p++;
2639 + gr->gr_ctx.length = *p++;
2640 + gr->gr_ctx.value = malloc(gr->gr_ctx.length);
2641 + memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
2642 + p += (((gr->gr_ctx.length + 3) & ~3) / 4);
2644 + gr->gr_token.length = *p++;
2645 + gr->gr_token.value = malloc(gr->gr_token.length);
2646 + memcpy(gr->gr_token.value, p, gr->gr_token.length);
2647 + p += (((gr->gr_token.length + 3) & ~3) / 4);
2649 + logmsg(LL_INFO, "do_nego_rpc: receive handle len %d, token len %d\n",
2650 + gr->gr_ctx.length, gr->gr_token.length);
2655 + * if return error, the lnd_rpc_err or lnd_gss_err is set.
2657 +int lgssc_negotiation(struct lgss_nego_data *lnd)
2659 + struct lgss_init_res gr;
2660 + gss_buffer_desc *recv_tokenp, send_token;
2661 + OM_uint32 maj_stat, min_stat, ret_flags;
2664 + logmsg(LL_TRACE, "start negotiation\n");
2666 + /* GSS context establishment loop. */
2667 + memset(&gr, 0, sizeof(gr));
2668 + recv_tokenp = GSS_C_NO_BUFFER;
2672 + /* print the token we just received */
2673 + if (recv_tokenp != GSS_C_NO_BUFFER) {
2674 + printerr(3, "The received token length %d\n",
2675 + recv_tokenp->length);
2676 + print_hexl(3, recv_tokenp->value, recv_tokenp->length);
2680 + maj_stat = gss_init_sec_context(&min_stat,
2683 + lnd->lnd_svc_name,
2685 + lnd->lnd_req_flags,
2687 + NULL, /* channel */
2689 + NULL, /* used mech */
2692 + NULL); /* time rec */
2694 + if (recv_tokenp != GSS_C_NO_BUFFER) {
2695 + gss_release_buffer(&min_stat, &gr.gr_token);
2696 + recv_tokenp = GSS_C_NO_BUFFER;
2699 + if (maj_stat != GSS_S_COMPLETE &&
2700 + maj_stat != GSS_S_CONTINUE_NEEDED) {
2701 + lnd->lnd_gss_err = maj_stat;
2703 + logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2704 + "failed init context\n");
2708 + if (send_token.length != 0) {
2709 + memset(&gr, 0, sizeof(gr));
2711 + /* print the token we are about to send */
2712 + printerr(3, "token being sent length %d\n",
2713 + send_token.length);
2714 + print_hexl(3, send_token.value, send_token.length);
2716 + call_stat = do_nego_rpc(lnd, &send_token, &gr);
2717 + gss_release_buffer(&min_stat, &send_token);
2719 + if (call_stat != 0 ||
2720 + (gr.gr_major != GSS_S_COMPLETE &&
2721 + gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
2722 + lnd->lnd_rpc_err = call_stat;
2723 + lnd->lnd_gss_err = gr.gr_major;
2725 + logmsg(LL_ERR, "call stat %d, major stat %x\n",
2726 + call_stat, gr.gr_major);
2730 + if (gr.gr_ctx.length != 0) {
2731 + if (lnd->lnd_rmt_ctx.value)
2732 + gss_release_buffer(&min_stat,
2733 + &lnd->lnd_rmt_ctx);
2734 + lnd->lnd_rmt_ctx = gr.gr_ctx;
2737 + if (gr.gr_token.length != 0) {
2738 + if (maj_stat != GSS_S_CONTINUE_NEEDED)
2740 + recv_tokenp = &gr.gr_token;
2744 + /* GSS_S_COMPLETE => check gss header verifier,
2745 + * usually checked in gss_validate
2747 + if (maj_stat == GSS_S_COMPLETE) {
2748 + lnd->lnd_established = 1;
2749 + lnd->lnd_seq_win = gr.gr_win;
2754 + /* End context negotiation loop. */
2755 + if (!lnd->lnd_established) {
2756 + if (gr.gr_token.length != 0)
2757 + gss_release_buffer(&min_stat, &gr.gr_token);
2759 + if (lnd->lnd_gss_err == GSS_S_COMPLETE)
2760 + lnd->lnd_rpc_err = -EACCES;
2762 + logmsg(LL_ERR, "context negotiation failed\n");
2766 + logmsg(LL_INFO, "successfully negotiated context\n");
2770 +int construct_service(struct keyring_upcall_param *kup)
2772 + const int max_namelen = 512;
2773 + char namebuf[max_namelen];
2776 + lassert(g_service == NULL);
2778 + if (kup->kup_svc >= LGSS_SVC_MAX) {
2779 + logmsg(LL_ERR, "invalid lgss service %d\n", kup->kup_svc);
2783 + if (lnet_nid2hostname(kup->kup_nid, namebuf, max_namelen))
2786 + alloc_size = 32 + strlen(namebuf);
2788 + g_service = malloc(alloc_size);
2789 + if (g_service == NULL) {
2790 + logmsg(LL_ERR, "can't malloc %d bytes\n", alloc_size);
2794 + snprintf(g_service, alloc_size, "%s@%s",
2795 + lgss_svc_name[kup->kup_svc], namebuf);
2797 + logmsg(LL_INFO, "constructed service: %s\n", g_service);
2802 + * if return error, the lnd_rpc_err or lnd_gss_err is set.
2804 +int lgssc_init_nego_data(struct lgss_nego_data *lnd,
2805 + struct keyring_upcall_param *kup,
2806 + lgss_auth_t authtype)
2808 + gss_buffer_desc sname;
2809 + OM_uint32 maj_stat, min_stat;
2811 + memset(lnd, 0, sizeof(*lnd));
2813 + lnd->lnd_uid = kup->kup_uid;
2814 + lnd->lnd_lsvc = kup->kup_svc;
2815 + lnd->lnd_uuid = kup->kup_tgt;
2817 + lnd->lnd_established = 0;
2818 + lnd->lnd_svc_name = GSS_C_NO_NAME;
2819 + lnd->lnd_cred = GSS_C_NO_CREDENTIAL;
2820 + lnd->lnd_ctx = GSS_C_NO_CONTEXT;
2821 + lnd->lnd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
2822 + lnd->lnd_seq_win = 0;
2824 + switch (authtype) {
2825 + case LGSS_AUTH_KRB5:
2826 + lnd->lnd_mech = (gss_OID) &krb5oid;
2827 + lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG;
2830 + logmsg(LL_ERR, "invalid auth type: %d\n", authtype);
2831 + lnd->lnd_rpc_err = -EACCES;
2835 + sname.value = g_service;
2836 + sname.length = strlen(g_service);
2838 + maj_stat = gss_import_name(&min_stat, &sname,
2839 + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
2840 + &lnd->lnd_svc_name);
2841 + if (maj_stat != GSS_S_COMPLETE) {
2842 + logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2843 + "can't import svc name\n");
2844 + lnd->lnd_gss_err = maj_stat;
2851 +void lgssc_fini_nego_data(struct lgss_nego_data *lnd)
2853 + OM_uint32 maj_stat, min_stat;
2855 + if (lnd->lnd_svc_name != GSS_C_NO_NAME) {
2856 + maj_stat = gss_release_name(&min_stat, &lnd->lnd_svc_name);
2857 + if (maj_stat != GSS_S_COMPLETE)
2858 + logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2859 + "can't release service name\n");
2862 + if (lnd->lnd_cred != GSS_C_NO_CREDENTIAL) {
2863 + maj_stat = gss_release_cred(&min_stat, &lnd->lnd_cred);
2864 + if (maj_stat != GSS_S_COMPLETE)
2865 + logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2866 + "can't release credential\n");
2871 +int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error)
2877 + logmsg(LL_TRACE, "revoking kernel key 0x%x\n", keyid);
2880 + end = buf + sizeof(buf);
2882 + WRITE_BYTES(&p, end, seqwin);
2883 + WRITE_BYTES(&p, end, rpc_error);
2884 + WRITE_BYTES(&p, end, gss_error);
2887 + if (keyctl_update(keyid, buf, p - buf)) {
2888 + if (errno != EAGAIN) {
2889 + logmsg(LL_ERR, "failed to revoke key 0x%x: %s\n",
2890 + keyid, strerror(errno));
2894 + logmsg(LL_WARN, "revoke key 0x%x too soon, try again\n", keyid);
2899 + logmsg(LL_INFO, "successfully revoke key 0x%x\n", keyid);
2904 +int update_kernel_key(key_serial_t keyid,
2905 + struct lgss_nego_data *lnd,
2906 + gss_buffer_desc *ctx_token)
2908 + char *buf = NULL, *p = NULL, *end = NULL;
2909 + unsigned int buf_size = 0;
2912 + logmsg(LL_TRACE, "updating kernel key 0x%x\n", keyid);
2914 + buf_size = sizeof(lnd->lnd_seq_win) +
2915 + sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length +
2916 + sizeof(ctx_token->length) + ctx_token->length;
2917 + buf = malloc(buf_size);
2918 + if (buf == NULL) {
2919 + logmsg(LL_ERR, "failed to alloc key update buf: size %d\n",
2925 + end = buf + buf_size;
2928 + if (WRITE_BYTES(&p, end, lnd->lnd_seq_win))
2930 + if (write_buffer(&p, end, &lnd->lnd_rmt_ctx))
2932 + if (write_buffer(&p, end, ctx_token))
2936 + if (keyctl_update(keyid, buf, p - buf)) {
2937 + if (errno != EAGAIN) {
2938 + logmsg(LL_ERR, "failed to update key 0x%x: %s\n",
2939 + keyid, strerror(errno));
2943 + logmsg(LL_WARN, "update key 0x%x too soon, try again\n", keyid);
2949 + logmsg(LL_INFO, "successfully updated key 0x%x\n", keyid);
2956 + * note we can't assume authority in child process
2958 +int lgssc_kr_negotiate(key_serial_t keyid, struct keyring_upcall_param *kup)
2960 + struct lgss_nego_data lnd;
2961 + gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
2962 + OM_uint32 min_stat;
2965 + logmsg(LL_TRACE, "child start on behalf of key 0x%x\n", keyid);
2967 + if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) {
2968 + logmsg(LL_ERR, "key 0x%x, failed set gids to %u: %s\n",
2969 + keyid, kup->kup_gid, strerror(errno));
2972 + if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) {
2973 + logmsg(LL_ERR, "key 0x%x, failed set uids to %u: %s\n",
2974 + keyid, kup->kup_uid, strerror(errno));
2978 + * link to session keyring, allow the key to be found.
2980 + if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) {
2981 + logmsg(LL_ERR, "key 0x%x, failed to link to session "
2982 + "keyring: %s\n", keyid, strerror(errno));
2983 + error_kernel_key(keyid, -EACCES, 0);
2988 + if (construct_service(kup)) {
2989 + error_kernel_key(keyid, -EACCES, 0);
2993 + if (1/* kup->kup_uid == 0 FIXME */) {
2994 + gssd_setup_krb5_user_gss_ccache(kup->kup_uid, g_service);
2997 + if (lgssc_init_nego_data(&lnd, kup, LGSS_AUTH_KRB5)) {
2998 + error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
3002 + rc = lgssc_negotiation(&lnd);
3004 + error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
3008 + rc = serialize_context_for_kernel(lnd.lnd_ctx, &token, lnd.lnd_mech);
3010 + error_kernel_key(keyid, rc, lnd.lnd_gss_err);
3012 + logmsg(LL_ERR, "failed to export context\n");
3016 + rc = update_kernel_key(keyid, &lnd, &token);
3021 + logmsg(LL_INFO, "key update OK!\n");
3023 + if (token.length != 0)
3024 + gss_release_buffer(&min_stat, &token);
3026 + lgssc_fini_nego_data(&lnd);
3029 + if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) {
3030 + logmsg(LL_ERR, "failed to unlink key %d: %s\n",
3031 + keyid, strerror(errno));
3037 +/****************************************
3039 + ****************************************/
3041 +int main(int argc, char *argv[])
3043 + struct keyring_upcall_param uparam;
3044 + key_serial_t keyid;
3045 + key_serial_t /*tring, pring, */sring;
3046 + key_serial_t inst_keyring;
3050 + if (argc != 10 + 1) {
3051 + logmsg(LL_ERR, "Invalid parameter number %d\n", argc);
3056 + logmsg(LL_TRACE, "OP: %s\n", argv[1]);
3057 + logmsg(LL_TRACE, "KeyID: %s\n", argv[2]);
3058 + logmsg(LL_TRACE, "KeyType: %s\n", argv[3]);
3059 + logmsg(LL_TRACE, "KeyDesc: %s\n", argv[4]);
3060 + logmsg(LL_TRACE, "COInfo: %s\n", argv[5]);
3061 + logmsg(LL_TRACE, "UID: %s\n", argv[6]);
3062 + logmsg(LL_TRACE, "GID: %s\n", argv[7]);
3063 + logmsg(LL_TRACE, "TKeyring: %s\n", argv[8]);
3064 + logmsg(LL_TRACE, "PKeyring: %s\n", argv[9]);
3065 + logmsg(LL_TRACE, "SKeyring: %s\n", argv[10]);
3067 + logmsg(LL_INFO, "[%u/%u]: key %s, desc %s, uid %s, sring %s\n",
3068 + getuid(), geteuid(),
3069 + argv[2], argv[4], argv[6], argv[10]);
3071 + memset(&uparam, 0, sizeof(uparam));
3073 + if (strcmp(argv[1], "create") != 0) {
3074 + logmsg(LL_ERR, "invalid OP %s\n", argv[1]);
3078 + if (sscanf(argv[2], "%d", &keyid) != 1) {
3079 + logmsg(LL_ERR, "can't extract KeyID\n");
3083 + if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) {
3084 + logmsg(LL_ERR, "can't extract uid\n");
3088 + if (sscanf(argv[10], "%d", &sring) != 1) {
3089 + logmsg(LL_ERR, "can't extract session keyring\n");
3093 + if (sscanf(argv[5], "%d:%d:%Lx:%s", &is_root, &uparam.kup_svc,
3094 + &uparam.kup_nid, uparam.kup_tgt) != 4) {
3095 + logmsg(LL_ERR, "can't extract callout info: %s\n", argv[5]);
3098 + logmsg(LL_INFO, "coinfo: fl %d, svc %d, nid 0x%Lx, tgt %s\n",
3099 + is_root, uparam.kup_svc, uparam.kup_nid, uparam.kup_tgt);
3104 + inst_keyring = KEY_SPEC_SESSION_KEYRING;
3106 + if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
3107 + logmsg(LL_ERR, "key instantiate: %s\n", strerror(errno));
3112 + if (child == -1) {
3113 + logmsg(LL_ERR, "can't create child: %s\n", strerror(errno));
3115 + } else if (child == 0) {
3116 + return lgssc_kr_negotiate(keyid, &uparam);
3121 diff -rNup nfs-utils-1.0.10/utils/gssd/l_idmap.c nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c
3122 --- nfs-utils-1.0.10/utils/gssd/l_idmap.c 1969-12-31 17:00:00.000000000 -0700
3123 +++ nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c 2007-05-15 13:01:35.000000000 -0600
3125 +#include <sys/types.h>
3126 +#include <stdlib.h>
3129 +#include "lsupport.h"
3131 +int main(int argc, char **argv)
3139 + "%s <princ> <nid>\n",
3140 + basename(argv[0]));
3144 + nid = libcfs_str2nid(argv[2]);
3145 + if (nid == LNET_NID_ANY) {
3146 + printf("parse nid %s failed\n", argv[2]);
3149 + rc = lookup_mapping(argv[1], nid, &uid);
3151 + printf("lookup mapping failed\n");
3155 + printf("principal: %s\n"
3158 + argv[1], nid, uid);
3162 diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.c nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c
3163 --- nfs-utils-1.0.10/utils/gssd/lsupport.c 1969-12-31 17:00:00.000000000 -0700
3164 +++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c 2007-05-15 13:01:35.000000000 -0600
3167 + * Copyright (c) 2005 Cluster File Systems, Inc.
3169 + * This file is part of Lustre, http://www.lustre.org.
3171 + * Lustre is free software; you can redistribute it and/or
3172 + * modify it under the terms of version 2 of the GNU General Public
3173 + * License as published by the Free Software Foundation.
3175 + * Lustre is distributed in the hope that it will be useful,
3176 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3177 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3178 + * GNU General Public License for more details.
3180 + * You should have received a copy of the GNU General Public License
3181 + * along with Lustre; if not, write to the Free Software
3182 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3185 +#ifndef _GNU_SOURCE
3186 +#define _GNU_SOURCE
3188 +#include "config.h"
3189 +#include <sys/param.h>
3190 +#include <sys/utsname.h>
3191 +#include <sys/stat.h>
3192 +#include <sys/socket.h>
3193 +#include <arpa/inet.h>
3194 +#include <sys/types.h>
3195 +#include <sys/ipc.h>
3196 +#include <sys/sem.h>
3199 +#include <stdlib.h>
3202 +#include <string.h>
3203 +#include <dirent.h>
3206 +#include <signal.h>
3207 +#include <unistd.h>
3209 +#include <assert.h>
3210 +#ifdef HAVE_GETHOSTBYNAME
3211 +# include <netdb.h>
3214 +#include "err_util.h"
3216 +#include "lsupport.h"
3218 +/****************************************
3219 + * exclusive startup *
3220 + ****************************************/
3222 +static struct __sem_s {
3227 + [GSSD_CLI] = { "client", 0x3a92d473, 0 },
3228 + [GSSD_SVC] = { "server", 0x3b92d473, 0 },
3231 +void gssd_init_unique(int type)
3233 + struct __sem_s *sem = &sems[type];
3234 + struct sembuf sembuf;
3236 + assert(type == GSSD_CLI || type == GSSD_SVC);
3239 + sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
3240 + if (sem->sem_id == -1) {
3241 + if (errno != EEXIST) {
3242 + printerr(0, "Create sem: %s\n", strerror(errno));
3246 + /* already exist. Note there's still a small window racing
3247 + * with other processes, due to the stupid semaphore semantics.
3249 + sem->sem_id = semget(sem->sem_key, 0, 0700);
3250 + if (sem->sem_id == -1) {
3251 + if (errno == ENOENT) {
3252 + printerr(0, "another instance just exit, "
3257 + printerr(0, "Obtain sem: %s\n", strerror(errno));
3263 + if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
3264 + printerr(0, "Initialize sem: %s\n",
3270 + sembuf.sem_num = 0;
3271 + sembuf.sem_op = -1;
3272 + sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
3274 + if (semop(sem->sem_id, &sembuf, 1) != 0) {
3275 + if (errno == EAGAIN) {
3276 + printerr(0, "Another instance is running, exit\n");
3279 + printerr(0, "Grab sem: %s\n", strerror(errno));
3283 + printerr(2, "Successfully created %s global identity\n", sem->name);
3286 +void gssd_exit_unique(int type)
3288 + assert(type == GSSD_CLI || type == GSSD_SVC);
3291 + * do nothing. we can't remove the sem here, otherwise the race
3292 + * window would be much bigger. So it's sad we have to leave the
3293 + * sem in the system forever.
3297 +/****************************************
3298 + * client side resolvation: *
3299 + * lnd/netid/nid => hostname *
3300 + ****************************************/
3302 +char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
3304 +typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
3305 + char *buf, int buflen);
3307 +/* FIXME what about IPv6? */
3309 +int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3310 + char *buf, int buflen)
3312 + struct hostent *ent;
3314 + addr = htonl(addr);
3315 + ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
3317 + printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
3320 + if (strlen(ent->h_name) >= buflen) {
3321 + printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
3324 + strcpy(buf, ent->h_name);
3326 + printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
3327 + lnd, net, addr, buf);
3332 +int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3333 + char *buf, int buflen)
3335 + struct utsname uts;
3336 + struct hostent *ent;
3339 + printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
3343 + if (uname(&uts)) {
3344 + printerr(0, "%s: failed obtain local machine name\n", lnd);
3348 + ent = gethostbyname(uts.nodename);
3350 + printerr(0, "%s: failed obtain canonical name of %s\n",
3351 + lnd, uts.nodename);
3355 + if (strlen(ent->h_name) >= buflen) {
3356 + printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
3359 + strcpy(buf, ent->h_name);
3361 + printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
3365 +static int is_space(char c)
3367 + return (c == ' ' || c == '\t' || c == '\n');
3371 +int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3372 + char *namebuf, int namebuflen)
3374 + const int bufsize = PATH_MAX + 256;
3375 + char buf[bufsize], *head, *tail;
3378 + sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
3379 + printerr(2, "cmd: %s\n", buf);
3381 + fghn = popen(buf, "r");
3382 + if (fghn == NULL) {
3383 + printerr(0, "failed to call %s\n", gethostname_ex);
3387 + head = fgets(buf, bufsize, fghn);
3388 + if (head == NULL) {
3389 + printerr(0, "can't read from %s\n", gethostname_ex);
3392 + if (pclose(fghn) == -1)
3393 + printerr(1, "pclose failed, continue\n");
3395 + /* trim head/tail space */
3396 + while (is_space(*head))
3399 + tail = head + strlen(head);
3400 + if (tail <= head) {
3401 + printerr(0, "no output from %s\n", gethostname_ex);
3404 + while (is_space(*(tail - 1)))
3406 + if (tail <= head) {
3407 + printerr(0, "output are all space from %s\n", gethostname_ex);
3412 + /* start with '@' means error msg */
3413 + if (head[0] == '@') {
3414 + printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
3418 + if (tail - head > namebuflen) {
3419 + printerr(0, "external hostname too long: %s\n", head);
3423 + printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
3424 + lnd, net, addr, head);
3425 + strcpy(namebuf, head);
3431 + lnd_nid2hostname_t *nid2name;
3432 +} converter[LND_ENUM_END_MARKER] = {
3433 + {"UNUSED0", NULL},
3434 + [QSWLND] = { "QSWLND", external_nid2hostname},
3435 + [SOCKLND] = { "SOCKLND", socklnd_nid2hostname },
3436 + [GMLND] = { "GMLND", external_nid2hostname},
3437 + [PTLLND] = { "PTLLND", external_nid2hostname },
3438 + [O2IBLND] = { "O2IBLND", socklnd_nid2hostname }, /* XXX */
3439 + [CIBLND] = { "CIBLND", external_nid2hostname },
3440 + [OPENIBLND] = { "OPENIBLND",external_nid2hostname },
3441 + [IIBLND] = { "IIBLND", external_nid2hostname },
3442 + [LOLND] = { "LOLND", lolnd_nid2hostname },
3443 + [RALND] = { "RALND", external_nid2hostname },
3444 + [VIBLND] = { "VIBLND", external_nid2hostname },
3447 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
3449 + uint32_t lnd, net, addr;
3451 + addr = LNET_NIDADDR(nid);
3452 + net = LNET_NIDNET(nid);
3453 + lnd = LNET_NETTYP(net);
3455 + if (lnd >= LND_ENUM_END_MARKER) {
3456 + printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
3460 + if (converter[lnd].nid2name == NULL) {
3461 + printerr(0, "ERROR: %s converter not ready\n",
3462 + converter[lnd].name);
3466 + return converter[lnd].nid2name(converter[lnd].name, net, addr,
3471 +/****************************************
3472 + * lnet support routine *
3473 + * (from lnet/libcfs/nidstrings.c *
3474 + ****************************************/
3476 +#define LNET_NIDSTR_SIZE 32 /* size of each one (see below for usage) */
3478 +static int libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
3479 +static void libcfs_ip_addr2str(uint32_t addr, char *str);
3480 +static int libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
3481 +static void libcfs_decnum_addr2str(uint32_t addr, char *str);
3482 +static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
3483 +static int libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
3489 + void (*nf_addr2str)(uint32_t addr, char *str);
3490 + int (*nf_str2addr)(char *str, int nob, uint32_t *addr);
3493 +static struct netstrfns libcfs_netstrfns[] = {
3494 + {/* .nf_type */ LOLND,
3495 + /* .nf_name */ "lo",
3496 + /* .nf_modname */ "klolnd",
3497 + /* .nf_addr2str */ libcfs_decnum_addr2str,
3498 + /* .nf_str2addr */ libcfs_lo_str2addr},
3499 + {/* .nf_type */ SOCKLND,
3500 + /* .nf_name */ "tcp",
3501 + /* .nf_modname */ "ksocklnd",
3502 + /* .nf_addr2str */ libcfs_ip_addr2str,
3503 + /* .nf_str2addr */ libcfs_ip_str2addr},
3504 + {/* .nf_type */ O2IBLND,
3505 + /* .nf_name */ "o2ib",
3506 + /* .nf_modname */ "ko2iblnd",
3507 + /* .nf_addr2str */ libcfs_ip_addr2str,
3508 + /* .nf_str2addr */ libcfs_ip_str2addr},
3509 + {/* .nf_type */ CIBLND,
3510 + /* .nf_name */ "cib",
3511 + /* .nf_modname */ "kciblnd",
3512 + /* .nf_addr2str */ libcfs_ip_addr2str,
3513 + /* .nf_str2addr */ libcfs_ip_str2addr},
3514 + {/* .nf_type */ OPENIBLND,
3515 + /* .nf_name */ "openib",
3516 + /* .nf_modname */ "kopeniblnd",
3517 + /* .nf_addr2str */ libcfs_ip_addr2str,
3518 + /* .nf_str2addr */ libcfs_ip_str2addr},
3519 + {/* .nf_type */ IIBLND,
3520 + /* .nf_name */ "iib",
3521 + /* .nf_modname */ "kiiblnd",
3522 + /* .nf_addr2str */ libcfs_ip_addr2str,
3523 + /* .nf_str2addr */ libcfs_ip_str2addr},
3524 + {/* .nf_type */ VIBLND,
3525 + /* .nf_name */ "vib",
3526 + /* .nf_modname */ "kviblnd",
3527 + /* .nf_addr2str */ libcfs_ip_addr2str,
3528 + /* .nf_str2addr */ libcfs_ip_str2addr},
3529 + {/* .nf_type */ RALND,
3530 + /* .nf_name */ "ra",
3531 + /* .nf_modname */ "kralnd",
3532 + /* .nf_addr2str */ libcfs_ip_addr2str,
3533 + /* .nf_str2addr */ libcfs_ip_str2addr},
3534 + {/* .nf_type */ QSWLND,
3535 + /* .nf_name */ "elan",
3536 + /* .nf_modname */ "kqswlnd",
3537 + /* .nf_addr2str */ libcfs_decnum_addr2str,
3538 + /* .nf_str2addr */ libcfs_num_str2addr},
3539 + {/* .nf_type */ GMLND,
3540 + /* .nf_name */ "gm",
3541 + /* .nf_modname */ "kgmlnd",
3542 + /* .nf_addr2str */ libcfs_hexnum_addr2str,
3543 + /* .nf_str2addr */ libcfs_num_str2addr},
3544 + {/* .nf_type */ PTLLND,
3545 + /* .nf_name */ "ptl",
3546 + /* .nf_modname */ "kptllnd",
3547 + /* .nf_addr2str */ libcfs_decnum_addr2str,
3548 + /* .nf_str2addr */ libcfs_num_str2addr},
3549 + /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */
3550 + {/* .nf_type */ -1},
3553 +const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
3556 +libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
3563 +libcfs_ip_addr2str(uint32_t addr, char *str)
3565 + snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
3566 + (addr >> 24) & 0xff, (addr >> 16) & 0xff,
3567 + (addr >> 8) & 0xff, addr & 0xff);
3570 +/* CAVEAT EMPTOR XscanfX
3571 + * I use "%n" at the end of a sscanf format to detect trailing junk. However
3572 + * sscanf may return immediately if it sees the terminating '0' in a string, so
3573 + * I initialise the %n variable to the expected length. If sscanf sets it;
3574 + * fine, if it doesn't, then the scan ended at the end of the string, which is
3578 +libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
3584 + int n = nob; /* XscanfX */
3587 + if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
3589 + (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
3590 + (c & ~0xff) == 0 && (d & ~0xff) == 0) {
3591 + *addr = ((a<<24)|(b<<16)|(c<<8)|d);
3595 +#ifdef HAVE_GETHOSTBYNAME
3596 + /* known hostname? */
3597 + if (('a' <= str[0] && str[0] <= 'z') ||
3598 + ('A' <= str[0] && str[0] <= 'Z')) {
3601 + tmp = malloc(nob + 1);
3602 + if (tmp != NULL) {
3603 + struct hostent *he;
3605 + memcpy(tmp, str, nob);
3608 + he = gethostbyname(tmp);
3614 + uint32_t ip = *(uint32_t *)he->h_addr;
3616 + *addr = ntohl(ip);
3626 +libcfs_decnum_addr2str(uint32_t addr, char *str)
3628 + snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
3632 +libcfs_hexnum_addr2str(uint32_t addr, char *str)
3634 + snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
3638 +libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
3643 + if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
3647 + if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
3651 + if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
3657 +static struct netstrfns *
3658 +libcfs_lnd2netstrfns(int lnd)
3663 + for (i = 0; i < libcfs_nnetstrfns; i++)
3664 + if (lnd == libcfs_netstrfns[i].nf_type)
3665 + return &libcfs_netstrfns[i];
3670 +static struct netstrfns *
3671 +libcfs_str2net_internal(char *str, uint32_t *net)
3673 + struct netstrfns *nf;
3678 + for (i = 0; i < libcfs_nnetstrfns; i++) {
3679 + nf = &libcfs_netstrfns[i];
3680 + if (nf->nf_type >= 0 &&
3681 + !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
3685 + if (i == libcfs_nnetstrfns)
3688 + nob = strlen(nf->nf_name);
3690 + if (strlen(str) == (unsigned int)nob) {
3693 + if (nf->nf_type == LOLND) /* net number not allowed */
3698 + if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
3699 + i != (int)strlen(str))
3703 + *net = LNET_MKNET(nf->nf_type, netnum);
3708 +libcfs_str2nid(char *str)
3710 + char *sep = strchr(str, '@');
3711 + struct netstrfns *nf;
3715 + if (sep != NULL) {
3716 + nf = libcfs_str2net_internal(sep + 1, &net);
3718 + return LNET_NID_ANY;
3720 + sep = str + strlen(str);
3721 + net = LNET_MKNET(SOCKLND, 0);
3722 + nf = libcfs_lnd2netstrfns(SOCKLND);
3724 + return LNET_NID_ANY;
3727 + if (!nf->nf_str2addr(str, sep - str, &addr))
3728 + return LNET_NID_ANY;
3730 + return LNET_MKNID(net, addr);
3733 +/****************************************
3734 + * user mapping database handling *
3735 + * (very rudiment) *
3736 + ****************************************/
3738 +#define MAPPING_GROW_SIZE 512
3739 +#define MAX_LINE_LEN 256
3741 +struct user_map_item {
3742 + char *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
3747 +struct user_mapping {
3749 + struct user_map_item *items;
3752 +static struct user_mapping mapping = {0, NULL};
3753 +/* FIXME to be finished: monitor change of mapping database */
3754 +static int mapping_mtime = 0;
3756 +void cleanup_mapping(void)
3758 + if (mapping.items) {
3759 + for (; mapping.nitems > 0; mapping.nitems--)
3760 + free(mapping.items[mapping.nitems - 1].principal);
3761 + free(mapping.items);
3762 + mapping.items = NULL;
3766 +static int grow_mapping(int nitems)
3768 + struct user_map_item *new;
3769 + int oldsize, newsize;
3771 + oldsize = (mapping.nitems * sizeof(struct user_map_item) +
3772 + MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3773 + newsize = (nitems * sizeof(struct user_map_item) +
3774 + MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3775 + while (newsize <= oldsize)
3778 + newsize *= MAPPING_GROW_SIZE;
3779 + new = malloc(newsize);
3781 + printerr(0, "can't alloc mapping size %d\n", newsize);
3785 + if (mapping.items) {
3786 + memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
3787 + free(mapping.items);
3789 + mapping.items = new;
3793 +uid_t parse_uid(char *uidstr)
3795 + struct passwd *pw;
3799 + pw = getpwnam(uidstr);
3801 + return pw->pw_uid;
3803 + uid = strtol(uidstr, &p, 0);
3805 + return (uid_t) uid;
3810 +static int read_mapping_db(void)
3812 + char princ[MAX_LINE_LEN];
3813 + char nid_str[MAX_LINE_LEN];
3814 + char dest[MAX_LINE_LEN];
3815 + char linebuf[MAX_LINE_LEN];
3821 + /* cleanup old mappings */
3822 + cleanup_mapping();
3824 + f = fopen(MAPPING_DATABASE_FILE, "r");
3826 + printerr(0, "can't open mapping database: %s\n",
3827 + MAPPING_DATABASE_FILE);
3831 + while ((line = fgets(linebuf, MAX_LINE_LEN, f)) != NULL) {
3834 + if (strlen(line) >= MAX_LINE_LEN) {
3835 + printerr(0, "invalid mapping db: line too long (%d)\n",
3840 + if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
3841 + printerr(0, "mapping db: syntax error\n");
3845 + if (!strcmp(princ, "*")) {
3846 + printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n");
3849 + name = strdup(princ);
3851 + printerr(0, "fail to dup str %s\n", princ);
3856 + if (!strcmp(nid_str, "*")) {
3857 + nid = LNET_NID_ANY;
3859 + nid = libcfs_str2nid(nid_str);
3860 + if (nid == LNET_NID_ANY) {
3861 + printerr(0, "fail to parse nid %s\n", nid_str);
3867 + dest_uid = parse_uid(dest);
3868 + if (dest_uid == -1) {
3869 + printerr(0, "no valid user: %s\n", dest);
3874 + if (grow_mapping(mapping.nitems + 1)) {
3875 + printerr(0, "fail to grow mapping to %d\n",
3876 + mapping.nitems + 1);
3882 + mapping.items[mapping.nitems].principal = name;
3883 + mapping.items[mapping.nitems].nid = nid;
3884 + mapping.items[mapping.nitems].uid = dest_uid;
3886 + printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
3887 + name, nid_str, nid, dest_uid);
3894 +static inline int mapping_changed(void)
3898 + if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
3899 + /* stat failed, treat it like doesn't exist or be removed */
3900 + if (mapping_mtime == 0) {
3903 + printerr(0, "Warning: stat %s failed: %s\n",
3904 + MAPPING_DATABASE_FILE, strerror(errno));
3906 + mapping_mtime = 0;
3911 + if (st.st_mtime != mapping_mtime) {
3912 + mapping_mtime = st.st_mtime;
3919 +int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
3925 + /* FIXME race condition here */
3926 + if (mapping_changed()) {
3927 + if (read_mapping_db())
3928 + printerr(0, "all remote users will be denied\n");
3931 + for (n = 0; n < mapping.nitems; n++) {
3932 + struct user_map_item *entry = &mapping.items[n];
3934 + if (entry->nid != LNET_NID_ANY && entry->nid != nid)
3936 + if (!strcasecmp(entry->principal, princ)) {
3937 + printerr(1, "found mapping: %s ==> %d\n",
3938 + princ, entry->uid);
3939 + *uid = entry->uid;
3944 + printerr(2, "no mapping for %s/%#Lx\n", princ, nid);
3947 diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.h nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h
3948 --- nfs-utils-1.0.10/utils/gssd/lsupport.h 1969-12-31 17:00:00.000000000 -0700
3949 +++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h 2007-05-15 13:01:35.000000000 -0600
3951 +#ifndef __LIBCFS_H__
3952 +#define __LIBCFS_H__
3954 +#include <unistd.h>
3955 +#include <stdint.h>
3957 +#define GSSD_CLI (0)
3958 +#define GSSD_SVC (1)
3960 +void gssd_init_unique(int type);
3961 +void gssd_exit_unique(int type);
3964 + * copied from lustre source
3967 +#define LUSTRE_GSS_SVC_MDS 0
3968 +#define LUSTRE_GSS_SVC_OSS 1
3970 +struct lgssd_upcall_data {
3979 +#define GSSD_INTERFACE_VERSION (1)
3981 +struct lgssd_ioctl_param {
3982 + int version; /* in */
3983 + char *uuid; /* in */
3984 + int lustre_svc; /* in */
3985 + uid_t uid; /* in */
3986 + gid_t gid; /* in */
3987 + long send_token_size;/* in */
3988 + char *send_token; /* in */
3989 + long reply_buf_size; /* in */
3990 + char *reply_buf; /* in */
3991 + long status; /* out */
3992 + long reply_length; /* out */
3995 +#define GSSD_DEFAULT_GETHOSTNAME_EX "/etc/lustre/nid2hostname"
3996 +#define MAPPING_DATABASE_FILE "/etc/lustre/idmap.conf"
3998 +typedef uint64_t lnet_nid_t;
3999 +typedef uint32_t lnet_netid_t;
4001 +#define LNET_NID_ANY ((lnet_nid_t) -1)
4002 +#define LNET_PID_ANY ((lnet_pid_t) -1)
4005 + /* Only add to these values (i.e. don't ever change or redefine them):
4006 + * network addresses depend on them... */
4018 + LND_ENUM_END_MARKER
4021 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
4022 +void cleanup_mapping(void);
4023 +int lookup_mapping(char *princ, uint64_t nid, uid_t *uid);
4024 +lnet_nid_t libcfs_str2nid(char *str);
4026 +/* how an LNET NID encodes net:address */
4027 +#define LNET_NIDADDR(nid) ((uint32_t)((nid) & 0xffffffff))
4028 +#define LNET_NIDNET(nid) ((uint32_t)(((nid) >> 32)) & 0xffffffff)
4029 +#define LNET_MKNID(net,addr) ((((uint64_t)(net))<<32)|((uint64_t)(addr)))
4030 +/* how net encodes type:number */
4031 +#define LNET_NETNUM(net) ((net) & 0xffff)
4032 +#define LNET_NETTYP(net) (((net) >> 16) & 0xffff)
4033 +#define LNET_MKNET(typ,num) ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
4035 +#endif /* __LIBCFS_H__ */
4036 diff -rNup nfs-utils-1.0.10/utils/gssd/Makefile.am nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am
4037 --- nfs-utils-1.0.10/utils/gssd/Makefile.am 2007-05-15 13:02:26.000000000 -0600
4038 +++ nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am 2007-05-15 13:00:53.000000000 -0600
4040 ## Process this file with automake to produce Makefile.in
4042 -man8_MANS = gssd.man svcgssd.man
4047 -sbin_PREFIXED = gssd svcgssd
4048 -sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err
4049 +sbin_PREFIXED = lgssd lsvcgssd
4050 +sbin_PROGRAMS = $(sbin_PREFIXED)
4051 sbin_SCRIPTS = gss_destroy_creds
4054 - gss_destroy_creds \
4060 @@ -21,13 +15,15 @@ COMMON_SRCS = \
4078 @@ -38,13 +34,12 @@ gssd_SOURCES = \
4082 -gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
4083 -gssd_LDFLAGS = $(KRBLDFLAGS)
4084 +lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
4085 +lgssd_LDFLAGS = $(KRBLDFLAGS)
4087 -gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4088 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4089 +lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
4091 -svcgssd_SOURCES = \
4092 +lsvcgssd_SOURCES = \
4096 @@ -55,20 +50,11 @@ svcgssd_SOURCES = \
4101 - ../../support/nfs/libnfs.a \
4102 - $(RPCSECGSS_LIBS) -lnfsidmap \
4105 -svcgssd_LDFLAGS = $(KRBLDFLAGS)
4107 -svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4108 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4109 +lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
4111 -gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
4112 +lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
4114 -gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4115 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4116 +lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
4118 MAINTAINERCLEANFILES = Makefile.in
4120 @@ -92,23 +78,3 @@ uninstall-hook:
4124 -# XXX This makes some assumptions about what automake does.
4125 -# XXX But there is no install-man-hook or install-man-local.
4126 -install-man: install-man8 install-man-links
4127 -uninstall-man: uninstall-man8 uninstall-man-links
4130 - (cd $(DESTDIR)$(man8dir) && \
4131 - for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
4132 - inst=`echo $$m | sed -e 's/man$$/8/'`; \
4133 - rm -f $(RPCPREFIX)$$inst ; \
4134 - $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
4137 -uninstall-man-links:
4138 - (cd $(DESTDIR)$(man8dir) && \
4139 - for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
4140 - inst=`echo $$m | sed -e 's/man$$/8/'`; \
4141 - rm -f $(RPCPREFIX)$$inst ; \
4144 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c
4145 --- nfs-utils-1.0.10/utils/gssd/svcgssd.c 2006-08-07 00:40:50.000000000 -0600
4146 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c 2007-05-15 13:01:35.000000000 -0600
4148 #include <sys/types.h>
4149 #include <sys/stat.h>
4150 #include <sys/socket.h>
4151 -#include <rpc/rpc.h>
4159 -#include "nfslib.h"
4160 +#include <dirent.h>
4161 #include "svcgssd.h"
4162 #include "gss_util.h"
4163 #include "err_util.h"
4164 +#include "lsupport.h"
4169 + DIR *dir = opendir("/proc/self/fd");
4170 + if (dir != NULL) {
4171 + int dfd = dirfd(dir);
4174 + while ((d = readdir(dir)) != NULL) {
4176 + long n = strtol(d->d_name, &endp, 10);
4177 + if (*endp != '\0' && n >= min && n != dfd)
4182 + int fd = sysconf(_SC_OPEN_MAX);
4183 + while (--fd >= min)
4188 * mydaemon creates a pipe between the partent and child
4189 * process. The parent process will wait until the
4190 @@ -139,6 +160,7 @@ void
4193 /* destroy krb5 machine creds */
4194 + cleanup_mapping();
4195 printerr(1, "exiting on signal %d\n", signal);
4198 @@ -165,8 +187,8 @@ main(int argc, char *argv[])
4202 - int rpc_verbosity = 0;
4204 + int must_srv_mds = 0, must_srv_oss = 0;
4205 extern char *optarg;
4208 @@ -181,8 +203,13 @@ main(int argc, char *argv[])
4224 @@ -196,27 +223,18 @@ main(int argc, char *argv[])
4227 initerr(progname, verbosity, fg);
4228 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
4229 - authgss_set_debug_level(rpc_verbosity);
4231 - if (rpc_verbosity > 0)
4232 - printerr(0, "Warning: rpcsec_gss library does not "
4233 - "support setting debug level\n");
4236 if (gssd_check_mechs() != 0) {
4237 printerr(0, "ERROR: Problem with gssapi library\n");
4244 - signal(SIGINT, sig_die);
4245 - signal(SIGTERM, sig_die);
4246 - signal(SIGHUP, sig_hup);
4247 + if (gssd_get_local_realm()) {
4248 + printerr(0, "ERROR: Can't get Local Kerberos realm\n");
4252 - if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
4253 + if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
4254 printerr(0, "unable to obtain root (machine) credentials\n");
4255 printerr(0, "do you have a keytab entry for "
4256 "nfs/<your.host>@<YOUR.REALM> in "
4257 @@ -225,9 +243,23 @@ main(int argc, char *argv[])
4264 + * XXX: There is risk of memory leak for missing call
4265 + * cleanup_mapping() for SIGKILL and SIGSTOP.
4267 + signal(SIGINT, sig_die);
4268 + signal(SIGTERM, sig_die);
4269 + signal(SIGHUP, sig_hup);
4275 + gssd_init_unique(GSSD_SVC);
4278 + cleanup_mapping();
4279 printerr(0, "gssd_run returned!\n");
4282 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.h nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h
4283 --- nfs-utils-1.0.10/utils/gssd/svcgssd.h 2006-08-07 00:40:50.000000000 -0600
4284 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h 2007-05-15 13:01:35.000000000 -0600
4286 #include <sys/queue.h>
4287 #include <gssapi/gssapi.h>
4289 -void handle_nullreq(FILE *f);
4290 -void gssd_run(void);
4291 +int handle_nullreq(FILE *f);
4292 +void svcgssd_run(void);
4293 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
4294 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
4296 -#define GSSD_SERVICE_NAME "nfs"
4297 +extern char *mds_local_realm;
4298 +extern char *oss_local_realm;
4300 +#define GSSD_SERVICE_NAME "lustre"
4303 +#define GSSD_SERVICE_MDS "lustre_mds"
4304 +#define GSSD_SERVICE_OSS "lustre_oss"
4305 +#define LUSTRE_ROOT_NAME "lustre_root"
4306 +#define LUSTRE_ROOT_NAMELEN 11
4308 #endif /* _RPC_SVCGSSD_H_ */
4309 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c
4310 --- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c 2006-08-07 00:40:50.000000000 -0600
4311 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c 2007-05-15 13:01:35.000000000 -0600
4313 #include "svcgssd.h"
4314 #include "err_util.h"
4317 + * nfs4 in-kernel cache implementation make upcall failed directly
4318 + * if there's no listener detected. so here we should keep the init
4319 + * channel file open as possible as we can.
4321 + * unfortunately the proc doesn't support dir change notification.
4322 + * and when an entry get unlinked, we only got POLLIN event once,
4323 + * it's the only oppotunity we can close the file and startover.
4332 struct pollfd pollfd;
4333 + struct timespec halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
4335 -#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
4336 +#define NULLRPC_FILE "/proc/net/rpc/auth.ptlrpcs.init/channel"
4338 - f = fopen(NULLRPC_FILE, "rw");
4341 - printerr(0, "failed to open %s: %s\n",
4342 - NULLRPC_FILE, strerror(errno));
4345 - pollfd.fd = fileno(f);
4346 - pollfd.events = POLLIN;
4350 + while (f == NULL) {
4351 + f = fopen(NULLRPC_FILE, "rw");
4353 + printerr(4, "failed to open %s: %s\n",
4354 + NULLRPC_FILE, strerror(errno));
4355 + nanosleep(&halfsec, NULL);
4357 + printerr(1, "successfully open %s\n",
4362 + pollfd.fd = fileno(f);
4363 + pollfd.events = POLLIN;
4366 - printerr(1, "entering poll\n");
4367 - ret = poll(&pollfd, 1, -1);
4368 + ret = poll(&pollfd, 1, 1000);
4370 - printerr(1, "leaving poll\n");
4373 - if (save_err != EINTR)
4374 - printerr(0, "error return from poll: %s\n",
4375 - strerror(save_err));
4376 + printerr(0, "error return from poll: %s\n",
4377 + strerror(save_err));
4380 } else if (ret == 0) {
4381 - /* timeout; shouldn't happen. */
4382 + printerr(3, "poll timeout\n");
4385 printerr(0, "bug: unexpected poll return %d\n",
4389 - if (pollfd.revents & POLLIN)
4390 - handle_nullreq(f);
4391 + if (pollfd.revents & POLLIN) {
4392 + if (handle_nullreq(f) < 0) {
4400 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c
4401 --- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-08-07 00:40:50.000000000 -0600
4402 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c 2007-05-15 13:01:35.000000000 -0600
4405 #include <sys/param.h>
4406 #include <sys/stat.h>
4407 -#include <rpc/rpc.h>
4415 -#include <nfsidmap.h>
4418 #include "svcgssd.h"
4419 #include "gss_util.h"
4420 #include "err_util.h"
4421 #include "context.h"
4422 #include "cacheio.h"
4423 +#include "lsupport.h"
4425 extern char * mech2file(gss_OID mech);
4426 -#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
4427 -#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel"
4428 +#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel"
4429 +#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.init/channel"
4431 #define TOKEN_BUF_SIZE 8192
4437 - gid_t cr_groups[NGROUPS];
4438 + uint32_t cr_remote;
4439 + uint32_t cr_usr_root;
4440 + uint32_t cr_usr_mds;
4442 + uid_t cr_mapped_uid;
4447 @@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han
4448 gss_OID mech, gss_buffer_desc *context_token)
4454 - printerr(1, "doing downcall\n");
4455 + printerr(2, "doing downcall\n");
4456 if ((fname = mech2file(mech)) == NULL)
4458 f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
4459 @@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han
4460 qword_printhex(f, out_handle->value, out_handle->length);
4461 /* XXX are types OK for the rest of this? */
4462 qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
4463 + qword_printint(f, cred->cr_remote);
4464 + qword_printint(f, cred->cr_usr_root);
4465 + qword_printint(f, cred->cr_usr_mds);
4466 + qword_printint(f, cred->cr_mapped_uid);
4467 qword_printint(f, cred->cr_uid);
4468 qword_printint(f, cred->cr_gid);
4469 - qword_printint(f, cred->cr_ngroups);
4470 - for (i=0; i < cred->cr_ngroups; i++)
4471 - qword_printint(f, cred->cr_groups[i]);
4472 qword_print(f, fname);
4473 qword_printhex(f, context_token->value, context_token->length);
4475 @@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc *
4479 - printerr(1, "sending null reply\n");
4480 + printerr(2, "sending null reply\n");
4482 qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
4483 qword_addhex(&bp, &blen, in_token->value, in_token->length);
4484 @@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc *
4485 #define rpcsec_gsserr_credproblem 13
4486 #define rpcsec_gsserr_ctxproblem 14
4490 add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
4492 @@ -182,7 +185,9 @@ add_supplementary_groups(char *secname,
4500 get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
4502 @@ -248,7 +253,9 @@ out_free:
4510 print_hexl(int pri, unsigned char *cp, int length)
4512 @@ -285,12 +292,121 @@ print_hexl(int pri, unsigned char *cp, i
4520 +get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
4521 + lnet_nid_t nid, uint32_t lustre_svc)
4523 + u_int32_t maj_stat, min_stat;
4524 + gss_buffer_desc name;
4525 + char *sname, *realm, *slash;
4527 + gss_OID name_type = GSS_C_NO_OID;
4528 + struct passwd *pw;
4530 + cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
4531 + cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
4533 + maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
4534 + if (maj_stat != GSS_S_COMPLETE) {
4535 + pgsserr("get_ids: gss_display_name",
4536 + maj_stat, min_stat, mech);
4539 + if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
4540 + !(sname = calloc(name.length + 1, 1))) {
4541 + printerr(0, "WARNING: get_ids: error allocating %d bytes "
4542 + "for sname\n", name.length + 1);
4543 + gss_release_buffer(&min_stat, &name);
4546 + memcpy(sname, name.value, name.length);
4547 + printerr(1, "authenticated %s from %016llx\n", sname, nid);
4548 + gss_release_buffer(&min_stat, &name);
4550 + if (lustre_svc == LUSTRE_GSS_SVC_MDS)
4551 + lookup_mapping(sname, nid, &cred->cr_mapped_uid);
4553 + cred->cr_mapped_uid = -1;
4555 + realm = strchr(sname, '@');
4557 + printerr(0, "WARNNING: principal %s contains no realm name\n",
4559 + cred->cr_remote = (mds_local_realm != NULL);
4562 + if (!mds_local_realm)
4563 + cred->cr_remote = 1;
4566 + (strcasecmp(mds_local_realm, realm) != 0);
4569 + if (cred->cr_remote) {
4570 + if (cred->cr_mapped_uid != -1)
4572 + else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
4573 + strcmp(sname, "lustre_root") == 0)
4576 + printerr(0, "principal %s is remote without mapping\n",
4581 + slash = strchr(sname, '/');
4585 + if (!(pw = getpwnam(sname))) {
4586 + /* If client use machine credential, we map it to root, which
4587 + * will subject to further mapping by root-squash in kernel.
4589 + * MDS service keytab is treated as special user, also mapped
4590 + * to root. OSS service keytab can't be used as a user.
4592 + if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
4593 + printerr(2, "lustre_root principal, resolve to uid 0\n");
4595 + cred->cr_usr_root = 1;
4596 + } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
4597 + printerr(2, "mds service principal, resolve to uid 0\n");
4599 + cred->cr_usr_mds = 1;
4601 + cred->cr_uid = -1;
4602 + if (cred->cr_mapped_uid == -1) {
4603 + printerr(0, "invalid user %s\n", sname);
4606 + printerr(2, "user %s mapped to %u\n",
4607 + sname, cred->cr_mapped_uid);
4610 + cred->cr_uid = pw->pw_uid;
4611 + printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
4620 +typedef struct gss_union_ctx_id_t {
4621 + gss_OID mech_type;
4622 + gss_ctx_id_t internal_ctx_id;
4623 +} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
4626 + * return -1 only if we detect error during reading from upcall channel,
4627 + * all other cases return 0.
4630 handle_nullreq(FILE *f) {
4631 - /* XXX initialize to a random integer to reduce chances of unnecessary
4632 - * invalidation of existing ctx's on restarting svcgssd. */
4633 - static u_int32_t handle_seq = 0;
4634 + uint64_t handle_seq;
4635 char in_tok_buf[TOKEN_BUF_SIZE];
4636 char in_handle_buf[15];
4637 char out_handle_buf[15];
4638 @@ -302,10 +418,13 @@ handle_nullreq(FILE *f) {
4639 ignore_out_tok = {.value = NULL},
4640 /* XXX isn't there a define for this?: */
4641 null_token = {.value = NULL};
4642 + uint32_t lustre_svc;
4644 u_int32_t ret_flags;
4645 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
4646 gss_name_t client_name;
4647 gss_OID mech = GSS_C_NO_OID;
4648 + gss_cred_id_t svc_cred;
4649 u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0;
4650 u_int32_t ignore_min_stat;
4651 struct svc_cred cred;
4652 @@ -313,25 +432,31 @@ handle_nullreq(FILE *f) {
4653 static int lbuflen = 0;
4656 - printerr(1, "handling null request\n");
4657 + printerr(2, "handling null request\n");
4659 if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
4660 printerr(0, "WARNING: handle_nullreq: "
4661 "failed reading request\n");
4668 + qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
4669 + qword_get(&cp, (char *) &nid, sizeof(nid));
4670 + qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
4671 + printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
4672 + lustre_svc, nid, handle_seq);
4674 in_handle.length = (size_t) qword_get(&cp, in_handle.value,
4675 sizeof(in_handle_buf));
4676 - printerr(2, "in_handle: \n");
4677 - print_hexl(2, in_handle.value, in_handle.length);
4678 + printerr(3, "in_handle: \n");
4679 + print_hexl(3, in_handle.value, in_handle.length);
4681 in_tok.length = (size_t) qword_get(&cp, in_tok.value,
4682 sizeof(in_tok_buf));
4683 - printerr(2, "in_tok: \n");
4684 - print_hexl(2, in_tok.value, in_tok.length);
4685 + printerr(3, "in_tok: \n");
4686 + print_hexl(3, in_tok.value, in_tok.length);
4688 if (in_tok.length < 0) {
4689 printerr(0, "WARNING: handle_nullreq: "
4690 @@ -351,7 +476,13 @@ handle_nullreq(FILE *f) {
4691 memcpy(&ctx, in_handle.value, in_handle.length);
4694 - maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
4695 + svc_cred = gssd_select_svc_cred(lustre_svc);
4697 + printerr(0, "no service credential for svc %u\n", lustre_svc);
4701 + maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
4702 &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
4703 &mech, &out_tok, &ret_flags, NULL, NULL);
4705 @@ -369,7 +500,8 @@ handle_nullreq(FILE *f) {
4706 maj_stat, min_stat, mech);
4709 - if (get_ids(client_name, mech, &cred)) {
4711 + if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
4712 /* get_ids() prints error msg */
4713 maj_stat = GSS_S_BAD_NAME; /* XXX ? */
4714 gss_release_name(&ignore_min_stat, &client_name);
4715 @@ -377,10 +509,8 @@ handle_nullreq(FILE *f) {
4717 gss_release_name(&ignore_min_stat, &client_name);
4720 /* Context complete. Pass handle_seq in out_handle to use
4721 * for context lookup in the kernel. */
4723 out_handle.length = sizeof(handle_seq);
4724 memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
4726 @@ -404,8 +534,7 @@ out:
4727 free(ctx_token.value);
4728 if (out_tok.value != NULL)
4729 gss_release_buffer(&ignore_min_stat, &out_tok);
4730 - printerr(1, "finished handling null request\n");
4735 if (ctx != GSS_C_NO_CONTEXT)
4736 diff -rNup nfs-utils-1.0.10/utils/Makefile.am nfs-utils-1.0.10.lustre/utils/Makefile.am
4737 --- nfs-utils-1.0.10/utils/Makefile.am 2006-08-07 00:40:50.000000000 -0600
4738 +++ nfs-utils-1.0.10.lustre/utils/Makefile.am 2007-05-15 13:00:53.000000000 -0600
4771 MAINTAINERCLEANFILES = Makefile.in