1 diff -Nrup nfs-utils-1.0.11.lustre/configure.in nfs-utils-1.0.11/configure.in
2 --- nfs-utils-1.0.11.lustre/configure.in 2007-02-21 21:50:03.000000000 -0700
3 +++ nfs-utils-1.0.11/configure.in 2008-01-02 18:10:29.000000000 -0700
4 @@ -18,61 +18,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 @@ -82,38 +35,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 @@ -156,50 +77,15 @@ 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"])
130 -AC_CHECK_LIB(blkid, blkid_get_cache, [LIBBLKID="-lblkid"], AC_MSG_ERROR([libblkid needed]))
131 -AC_CHECK_HEADER(blkid/blkid.h, , AC_MSG_ERROR([Cannot file libblkid header file blkid/blkid.h]))
132 +PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
138 if test "$enable_gss" = yes; then
139 - dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
140 - AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
141 - AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
142 - dnl the nfs4_set_debug function doesn't appear in all version of the library
143 - AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
144 - AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
145 - [Whether nfs4_set_debug() is present in libnfsidmap]),)
147 dnl Check for Kerberos V5
150 - dnl This is not done until here because we need to have KRBLIBS set
151 - dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
152 - AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
153 - AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
154 - AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
158 dnl *************************************************************
159 @@ -311,33 +197,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
165 - support/export/Makefile
166 - support/include/nfs/Makefile
167 - support/include/rpcsvc/Makefile
168 - support/include/sys/fs/Makefile
169 - support/include/sys/Makefile
170 - support/include/Makefile
171 - support/misc/Makefile
172 - support/nfs/Makefile
174 - tools/getiversion/Makefile
175 - tools/locktest/Makefile
176 - tools/nlmtest/Makefile
177 - tools/rpcdebug/Makefile
178 - tools/rpcgen/Makefile
180 - utils/exportfs/Makefile
181 - utils/gssd/Makefile
182 - utils/idmapd/Makefile
183 - utils/lockd/Makefile
184 - utils/mount/Makefile
185 - utils/mountd/Makefile
186 - utils/nfsd/Makefile
187 - utils/nfsstat/Makefile
188 - utils/rquotad/Makefile
189 - utils/showmount/Makefile
190 - utils/statd/Makefile])
191 + utils/gssd/Makefile])
194 diff -Nrup nfs-utils-1.0.11.lustre/Makefile.am nfs-utils-1.0.11/Makefile.am
195 --- nfs-utils-1.0.11.lustre/Makefile.am 2007-02-21 21:50:03.000000000 -0700
196 +++ nfs-utils-1.0.11/Makefile.am 2008-01-02 18:10:29.000000000 -0700
198 ## Process this file with automake to produce Makefile.in
200 -SUBDIRS = tools support utils linux-nfs
203 MAINTAINERCLEANFILES = Makefile.in
205 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c nfs-utils-1.0.11/utils/gssd/cacheio.c
206 --- nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c 2007-02-21 21:50:03.000000000 -0700
207 +++ nfs-utils-1.0.11/utils/gssd/cacheio.c 2008-01-02 18:11:38.000000000 -0700
208 @@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in
210 while (*bp == ' ') bp++;
213 +// why should we clear *dest???
218 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.c nfs-utils-1.0.11/utils/gssd/context.c
219 --- nfs-utils-1.0.11.lustre/utils/gssd/context.c 2007-02-21 21:50:03.000000000 -0700
220 +++ nfs-utils-1.0.11/utils/gssd/context.c 2008-01-02 18:11:38.000000000 -0700
224 #include <gssapi/gssapi.h>
225 -#include <rpc/rpc.h>
226 -#include <rpc/auth_gss.h>
227 -#include "gss_util.h"
228 -#include "gss_oids.h"
229 -#include "err_util.h"
232 +# include "lgss_utils.h"
234 +# include "gss_util.h"
235 +# include "gss_oids.h"
236 +# include "err_util.h"
241 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.h nfs-utils-1.0.11/utils/gssd/context.h
242 --- nfs-utils-1.0.11.lustre/utils/gssd/context.h 2008-01-02 17:22:48.000000000 -0700
243 +++ nfs-utils-1.0.11/utils/gssd/context.h 2008-01-02 18:11:38.000000000 -0700
248 -#include <rpc/rpc.h>
250 /* Hopefully big enough to hold any serialized context */
251 #define MAX_CTX_LEN 4096
253 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c nfs-utils-1.0.11/utils/gssd/context_heimdal.c
254 --- nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c 2007-02-21 21:50:03.000000000 -0700
255 +++ nfs-utils-1.0.11/utils/gssd/context_heimdal.c 2008-01-02 18:11:38.000000000 -0700
257 #ifdef HAVE_COM_ERR_H
260 -#include "err_util.h"
261 -#include "gss_oids.h"
264 +# include "lgss_utils.h"
266 +# include "err_util.h"
267 +# include "gss_oids.h"
269 #include "write_bytes.h"
271 int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
272 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c nfs-utils-1.0.11/utils/gssd/context_lucid.c
273 --- nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c 2008-01-02 17:22:48.000000000 -0700
274 +++ nfs-utils-1.0.11/utils/gssd/context_lucid.c 2008-01-02 18:11:38.000000000 -0700
279 -#include "gss_util.h"
280 -#include "gss_oids.h"
281 -#include "err_util.h"
282 -#include "context.h"
286 #include <gssapi/gssapi.h>
288 @@ -53,6 +49,16 @@ typedef uint64_t OM_uint64;
290 #include <gssapi/gssapi_krb5.h>
293 +# include "lgss_utils.h"
295 +# include "gss_util.h"
296 +# include "gss_oids.h"
297 +# include "err_util.h"
299 +#include "write_bytes.h"
300 +#include "context.h"
303 write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
305 @@ -354,6 +360,7 @@ static int
306 prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
307 gss_buffer_desc *buf)
309 + static int constant_two = 2;
311 uint32_t v2_flags = 0;
312 gss_krb5_lucid_key_t enc_key;
313 @@ -372,7 +379,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
314 end = buf->value + MAX_CTX_LEN;
317 - if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
318 + if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
319 if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
322 @@ -387,7 +394,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
323 if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
325 /* Protocol 0 here implies DES3 or RC4 */
326 - printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
327 + printerr(3, "protocol %d\n", lctx->protocol);
328 if (lctx->protocol == 0) {
329 enctype = lctx->rfc1964_kd.ctx_key.type;
331 @@ -415,8 +422,8 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
335 - printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
336 - __FUNCTION__, numkeys, enctype, keysize);
337 + printerr(3, "serializing %d keys with enctype %d and size %d\n",
338 + numkeys, enctype, keysize);
339 if (WRITE_BYTES(&p, end, enctype)) goto out_err;
340 if (WRITE_BYTES(&p, end, keysize)) goto out_err;
341 if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
342 @@ -434,14 +441,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
346 - if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
348 - KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
350 - if (write_bytes(&p, end, derived_key.data,
351 - derived_key.length))
353 - free(derived_key.data);
355 + * RC4 is special, it dosen't need key derivation. Actually
356 + * the Ke is based on plain text. Here we just let all three
357 + * key identical, kernel will handle everything. --ericm
359 + if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
360 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
361 + lctx->rfc1964_kd.ctx_key.length))
364 + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
366 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
368 + if (write_bytes(&p, end, derived_key.data,
369 + derived_key.length))
371 + free(derived_key.data);
374 gss_krb5_lucid_key_t *keyptr;
375 uint32_t sign_usage, seal_usage;
376 @@ -451,6 +469,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
378 keyptr = &lctx->cfx_kd.ctx_key;
381 if (lctx->initiate == 1) {
382 sign_usage = KG_USAGE_INITIATOR_SIGN;
383 seal_usage = KG_USAGE_INITIATOR_SEAL;
384 @@ -458,6 +477,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
385 sign_usage = KG_USAGE_ACCEPTOR_SIGN;
386 seal_usage = KG_USAGE_ACCEPTOR_SEAL;
390 + * These are from rfc4142, but I don't understand: if we supply
391 + * different 'usage' value for client & server, then the peers
392 + * will have different derived keys. How could this work?
394 + * Here we simply use old SIGN/SEAL values until we find the
398 + sign_usage = KG_USAGE_SIGN;
399 + seal_usage = KG_USAGE_SEAL;
402 /* derive and send down: Ke, Ki, and Kc */
404 @@ -515,7 +547,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
405 gss_krb5_lucid_context_v1_t *lctx = 0;
408 - printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
409 + printerr(3, "lucid version!\n");
410 maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
412 if (maj_stat != GSS_S_COMPLETE) {
413 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c nfs-utils-1.0.11/utils/gssd/context_mit.c
414 --- nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c 2008-01-02 17:22:48.000000000 -0700
415 +++ nfs-utils-1.0.11/utils/gssd/context_mit.c 2008-01-02 18:11:38.000000000 -0700
418 #include <gssapi/gssapi.h>
420 -#include <rpc/auth_gss.h>
421 -#include "gss_util.h"
422 -#include "gss_oids.h"
423 -#include "err_util.h"
426 +# include "lgss_utils.h"
427 +# include "write_bytes.h"
429 +# include "gss_util.h"
430 +# include "gss_oids.h"
431 +# include "err_util.h"
436 @@ -333,12 +338,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
437 * keydata-2; ( Ki (Kseq for DES3) )
438 * keydata-3; ( Kc (derived checksum key) )
440 - if (kctx->initiate) {
441 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
444 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
446 + if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
447 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
449 /* Only applicable flag for this is initiator */
450 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c nfs-utils-1.0.11/utils/gssd/context_spkm3.c
451 --- nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c 2007-02-21 21:50:03.000000000 -0700
452 +++ nfs-utils-1.0.11/utils/gssd/context_spkm3.c 2008-01-02 18:11:38.000000000 -0700
456 #include <gssapi/gssapi.h>
457 -#include <rpc/rpc.h>
458 -#include <rpc/auth_gss.h>
459 #include "gss_util.h"
460 #include "gss_oids.h"
461 #include "err_util.h"
462 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.c nfs-utils-1.0.11/utils/gssd/err_util.c
463 --- nfs-utils-1.0.11.lustre/utils/gssd/err_util.c 2007-02-21 21:50:03.000000000 -0700
464 +++ nfs-utils-1.0.11/utils/gssd/err_util.c 2008-01-02 18:11:38.000000000 -0700
471 #include "err_util.h"
473 static int verbosity = 0;
474 @@ -91,3 +93,40 @@ printit:
475 /* reset the buffer */
476 memset(message_buf, 0, sizeof(message_buf));
479 +void print_hexl(int pri, unsigned char *cp, int length)
484 + printerr(pri, "length %d\n",length);
485 + printerr(pri, "\n");
487 + for (i = 0; i < length; i += 0x10) {
488 + printerr(pri, " %04x: ", (u_int)i);
490 + jm = jm > 16 ? 16 : jm;
492 + for (j = 0; j < jm; j++) {
494 + printerr(pri,"%02x ", (u_int)cp[i+j]);
496 + printerr(pri,"%02x", (u_int)cp[i+j]);
498 + for (; j < 16; j++) {
506 + for (j = 0; j < jm; j++) {
508 + c = isprint(c) ? c : '.';
509 + printerr(pri,"%c", c);
511 + printerr(pri,"\n");
515 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.h nfs-utils-1.0.11/utils/gssd/err_util.h
516 --- nfs-utils-1.0.11.lustre/utils/gssd/err_util.h 2007-02-21 21:50:03.000000000 -0700
517 +++ nfs-utils-1.0.11/utils/gssd/err_util.h 2008-01-02 18:11:38.000000000 -0700
520 void initerr(char *progname, int verbosity, int fg);
521 void printerr(int priority, char *format, ...);
522 +void print_hexl(int pri, unsigned char *cp, int length);
524 #endif /* _ERR_UTIL_H_ */
525 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c
526 --- nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c 2007-02-21 21:50:03.000000000 -0700
527 +++ nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c 2008-01-02 18:10:29.000000000 -0700
530 #include "write_bytes.h"
533 char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
536 @@ -102,3 +103,4 @@ main(int argc, char *argv[])
541 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.c nfs-utils-1.0.11/utils/gssd/gssd.c
542 --- nfs-utils-1.0.11.lustre/utils/gssd/gssd.c 2008-01-02 17:22:48.000000000 -0700
543 +++ nfs-utils-1.0.11/utils/gssd/gssd.c 2008-01-02 18:11:38.000000000 -0700
548 +#include <sys/types.h>
549 #include <sys/param.h>
550 #include <sys/socket.h>
551 -#include <rpc/rpc.h>
552 +#include <sys/wait.h>
553 +#include <sys/ipc.h>
554 +#include <sys/sem.h>
564 #include "err_util.h"
565 #include "gss_util.h"
566 #include "krb5_util.h"
567 +#include "lsupport.h"
569 char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
570 char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
571 char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
572 char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
573 int use_memcache = 0;
574 +int lgssd_mutex_downcall = -1;
578 +static int lgssd_create_mutex(int *semid)
583 + id = semget(IPC_PRIVATE, 1, IPC_CREAT);
585 + printerr(0, "semget: %s\n", strerror(errno));
590 + if (semctl(id, 0, SETVAL, arg) != 0) {
591 + printerr(0, "semctl: %s\n", strerror(errno));
592 + semctl(id, 1, IPC_RMID, arg);
600 +void lgssd_init_mutexs(void)
602 + if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
603 + printerr(0, "can't create downcall mutex\n");
608 +void lgssd_fini_mutexs(void)
612 + if (lgssd_mutex_downcall != -1)
613 + semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
616 +void lgssd_mutex_get(int semid)
618 + struct sembuf op[1] = { {0, -1, SEM_UNDO} };
621 + rc = semop(semid, op, 1);
623 + printerr(0, "exit on mutex_get err %d: %s\n",
624 + rc, strerror(errno));
629 +void lgssd_mutex_put(int semid)
631 + struct sembuf op[1] = { {0, 1, 0} };
634 + rc = semop(semid, op, 1);
636 + printerr(0, "ignore mutex_put err %d: %s\n",
637 + rc, strerror(errno));
641 +static void lgssd_cleanup(void)
645 + /* make sure all children finished */
647 + child_pid = waitpid(-1, NULL, 0);
651 + printerr(3, "cleanup: child %d terminated\n", child_pid);
654 + lgssd_fini_mutexs();
656 /* destroy krb5 machine creds */
657 gssd_destroy_krb5_machine_creds();
663 printerr(1, "exiting on signal %d\n", signal);
668 @@ -79,7 +166,7 @@ sig_hup(int signal)
670 usage(char *progname)
672 - fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
673 + fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
677 @@ -89,7 +176,6 @@ main(int argc, char *argv[])
681 - int rpc_verbosity = 0;
685 @@ -99,18 +185,12 @@ main(int argc, char *argv[])
690 - /* Accept but ignore this. Now the default. */
702 strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
703 if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
704 @@ -131,10 +211,6 @@ main(int argc, char *argv[])
708 - snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
709 - pipefs_dir, GSSD_SERVICE_NAME);
710 - if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
711 - errx(1, "pipefs_nfsdir path name too long");
713 if ((progname = strrchr(argv[0], '/')))
715 @@ -142,30 +218,42 @@ main(int argc, char *argv[])
718 initerr(progname, verbosity, fg);
719 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
720 - authgss_set_debug_level(rpc_verbosity);
722 - if (rpc_verbosity > 0)
723 - printerr(0, "Warning: rpcsec_gss library does not "
724 - "support setting debug level\n");
727 if (gssd_check_mechs() != 0)
728 errx(1, "Problem with gssapi library");
730 + if (gssd_get_local_realm())
731 + errx(1, "get local realm");
733 if (!fg && daemon(0, 0) < 0)
736 + /* This should be checked _after_ daemon(), because we need to own
737 + * the undo-able semaphore by this process
739 + gssd_init_unique(GSSD_CLI);
741 + /* Process keytab file and get machine credentials. This will modify
742 + * disk status so do it after we are sure we are the only instance
744 + if (gssd_refresh_krb5_machine_creds())
747 signal(SIGINT, sig_die);
748 signal(SIGTERM, sig_die);
749 signal(SIGHUP, sig_hup);
751 - /* Process keytab file and get machine credentials */
752 - gssd_refresh_krb5_machine_creds();
754 /* Determine Kerberos information from the kernel */
755 gssd_obtain_kernel_krb5_info();
758 + lgssd_init_mutexs();
760 + printerr(0, "lgssd initialized and ready to serve\n");
764 - printerr(0, "gssd_run returned!\n");
767 + printerr(0, "lgssd exiting\n");
770 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.h nfs-utils-1.0.11/utils/gssd/gssd.h
771 --- nfs-utils-1.0.11.lustre/utils/gssd/gssd.h 2008-01-02 17:22:48.000000000 -0700
772 +++ nfs-utils-1.0.11/utils/gssd/gssd.h 2008-01-02 18:11:38.000000000 -0700
774 #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_"
775 #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine"
776 #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
777 -#define GSSD_SERVICE_NAME "nfs"
778 -#define GSSD_SERVICE_NAME_LEN 3
779 +#define GSSD_SERVICE_MDS "lustre_mds"
780 +#define GSSD_SERVICE_OSS "lustre_oss"
781 +#define GSSD_SERVICE_MDS_NAMELEN 10
782 +#define GSSD_SERVICE_OSS_NAMELEN 10
784 +#define LUSTRE_ROOT_NAME "lustre_root"
785 +#define LUSTRE_ROOT_NAMELEN 11
788 * The gss mechanisms that we can handle
789 @@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
792 extern char pipefs_dir[PATH_MAX];
793 -extern char pipefs_nfsdir[PATH_MAX];
794 extern char keytabfile[PATH_MAX];
795 extern char ccachedir[PATH_MAX];
796 +extern char gethostname_ex[PATH_MAX];
797 extern int use_memcache;
799 TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
800 @@ -71,10 +76,6 @@ struct clnt_info {
811 @@ -85,8 +86,14 @@ void init_client_list(void);
812 int update_client_list(void);
813 void handle_krb5_upcall(struct clnt_info *clp);
814 void handle_spkm3_upcall(struct clnt_info *clp);
815 -int gssd_acquire_cred(char *server_name);
816 -void gssd_run(void);
817 +void lgssd_run(void);
820 +extern int lgssd_mutex_downcall;
822 +void lgssd_init_mutexs(void);
823 +void lgssd_fini_mutexs(void);
824 +void lgssd_mutex_get(int semid);
825 +void lgssd_mutex_put(int semid);
827 #endif /* _RPC_GSSD_H_ */
828 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c
829 --- nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c 2008-01-02 17:22:48.000000000 -0700
830 +++ nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c 2008-01-02 18:11:38.000000000 -0700
841 #include "err_util.h"
842 @@ -94,11 +98,13 @@ scan_poll_results(int ret)
850 struct sigaction dn_act;
852 + time_t child_check = 0;
855 /* Taken from linux/Documentation/dnotify.txt: */
856 dn_act.sa_sigaction = dir_notify_handler;
857 @@ -106,10 +112,10 @@ gssd_run()
858 dn_act.sa_flags = SA_SIGINFO;
859 sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
861 - if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
862 + if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
863 printerr(0, "ERROR: failed to open %s: %s\n",
864 - pipefs_nfsdir, strerror(errno));
866 + pipefs_dir, strerror(errno));
869 fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
870 fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
871 @@ -119,12 +125,30 @@ gssd_run()
873 while (dir_changed) {
875 + printerr(2, "pipefs root dir changed\n");
876 if (update_client_list()) {
877 printerr(0, "ERROR: couldn't update "
884 + /* every 5s cleanup possible zombies of child processes */
885 + if (time(NULL) - child_check >= 5) {
886 + printerr(3, "check zombie children...\n");
889 + child_pid = waitpid(-1, NULL, WNOHANG);
890 + if (child_pid <= 0)
893 + printerr(2, "terminate zombie child: %d\n",
897 + child_check = time(NULL);
900 /* race condition here: dir_changed could be set before we
901 * enter the poll, and we'd never notice if it weren't for the
903 @@ -139,6 +163,7 @@ gssd_run()
904 scan_poll_results(ret);
911 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c nfs-utils-1.0.11/utils/gssd/gssd_proc.c
912 --- nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c 2008-01-02 17:22:48.000000000 -0700
913 +++ nfs-utils-1.0.11/utils/gssd/gssd_proc.c 2008-01-02 18:11:38.000000000 -0700
917 #include <sys/param.h>
918 -#include <rpc/rpc.h>
919 #include <sys/stat.h>
920 #include <sys/socket.h>
921 #include <arpa/inet.h>
923 #include "gss_oids.h"
924 #include "krb5_util.h"
926 +#include "lsupport.h"
930 @@ -99,86 +99,10 @@ struct pollfd * pollarray;
932 int pollsize; /* the size of pollaray (in pollfd's) */
934 -/* XXX buffer problems: */
936 -read_service_info(char *info_file_name, char **servicename, char **servername,
937 - int *prog, int *vers, char **protocol) {
938 -#define INFOBUFLEN 256
939 - char buf[INFOBUFLEN];
940 - static char dummy[128];
942 - static char service[128];
943 - static char address[128];
946 - char protoname[16];
949 - struct hostent *ent = NULL;
952 - *servicename = *servername = *protocol = NULL;
954 - if ((fd = open(info_file_name, O_RDONLY)) == -1) {
955 - printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
959 - if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
963 - numfields = sscanf(buf,"RPC server: %127s\n"
964 - "service: %127s %15s version %15s\n"
966 - "protocol: %15s\n",
968 - service, program, version,
972 - if (numfields == 5) {
973 - strcpy(protoname, "tcp");
974 - } else if (numfields != 6) {
978 - /* check service, program, and version */
979 - if(memcmp(service, "nfs", 3)) return -1;
980 - *prog = atoi(program + 1); /* skip open paren */
981 - *vers = atoi(version);
982 - if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
985 - /* create service name */
986 - inaddr = inet_addr(address);
987 - if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
988 - printerr(0, "ERROR: can't resolve server %s name\n", address);
991 - if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
993 - memcpy(*servername, ent->h_name, strlen(ent->h_name));
994 - snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
995 - if (!(*servicename = calloc(strlen(buf) + 1, 1)))
997 - memcpy(*servicename, buf, strlen(buf));
999 - if (!(*protocol = strdup(protoname)))
1003 - printerr(0, "ERROR: failed to read service info\n");
1004 - if (fd != -1) close(fd);
1005 - if (*servername) free(*servername);
1006 - if (*servicename) free(*servicename);
1007 - if (*protocol) free(*protocol);
1012 destroy_client(struct clnt_info *clp)
1014 + printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
1015 if (clp->krb5_poll_index != -1)
1016 memset(&pollarray[clp->krb5_poll_index], 0,
1017 sizeof(struct pollfd));
1018 @@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
1019 if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
1020 if (clp->dirname) free(clp->dirname);
1021 if (clp->servicename) free(clp->servicename);
1022 - if (clp->servername) free(clp->servername);
1023 - if (clp->protocol) free(clp->protocol);
1027 @@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info
1031 - char info_file_name[32];
1033 if (clp->krb5_fd == -1) {
1034 snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
1035 @@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info
1037 if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
1039 - snprintf(info_file_name, sizeof(info_file_name), "%s/info",
1041 - if ((clp->servicename == NULL) &&
1042 - read_service_info(info_file_name, &clp->servicename,
1043 - &clp->servername, &clp->prog, &clp->vers,
1049 @@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
1051 pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
1052 pollarray[clp->krb5_poll_index].events |= POLLIN;
1053 + printerr(2, "monitoring krb5 channel under %s\n",
1057 if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
1058 @@ -386,67 +302,106 @@ find_client(char *dirname)
1060 update_client_list(void)
1062 - struct dirent **namelist;
1063 + char lustre_dir[PATH_MAX];
1064 + struct dirent lustre_dirent = { .d_name = "lustre" };
1065 + struct dirent *namelist[1];
1066 + struct stat statbuf;
1069 - if (chdir(pipefs_nfsdir) < 0) {
1070 + if (chdir(pipefs_dir) < 0) {
1071 printerr(0, "ERROR: can't chdir to %s: %s\n",
1072 - pipefs_nfsdir, strerror(errno));
1073 + pipefs_dir, strerror(errno));
1077 - j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
1079 - printerr(0, "ERROR: can't scandir %s: %s\n",
1080 - pipefs_nfsdir, strerror(errno));
1082 + snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
1083 + if (stat(lustre_dir, &statbuf) == 0) {
1084 + namelist[0] = &lustre_dirent;
1086 + printerr(2, "re-processing lustre directory\n");
1088 + namelist[0] = NULL;
1090 + printerr(2, "lustre directory not exist\n");
1093 update_old_clients(namelist, j);
1094 for (i=0; i < j; i++) {
1095 - if (i < FD_ALLOC_BLOCK
1096 - && !strncmp(namelist[i]->d_name, "clnt", 4)
1097 - && !find_client(namelist[i]->d_name))
1098 + if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
1099 process_clnt_dir(namelist[i]->d_name);
1100 - free(namelist[i]);
1108 +/* Context creation response. */
1109 +struct lustre_gss_init_res {
1110 + gss_buffer_desc gr_ctx; /* context handle */
1111 + u_int gr_major; /* major status */
1112 + u_int gr_minor; /* minor status */
1113 + u_int gr_win; /* sequence window */
1114 + gss_buffer_desc gr_token; /* token */
1117 +struct lustre_gss_data {
1118 + int lgd_established;
1119 + int lgd_lustre_svc; /* mds/oss */
1120 + int lgd_uid; /* uid */
1121 + char *lgd_uuid; /* client device uuid */
1122 + gss_name_t lgd_name; /* service name */
1124 + gss_OID lgd_mech; /* mech OID */
1125 + u_int lgd_req_flags; /* request flags */
1126 + gss_cred_id_t lgd_cred; /* credential */
1127 + gss_ctx_id_t lgd_ctx; /* session context */
1128 + gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */
1129 + uint32_t lgd_seq_win; /* sequence window */
1136 -do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
1137 - gss_buffer_desc *context_token)
1138 +do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
1139 + struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
1141 char *buf = NULL, *p = NULL, *end = NULL;
1142 unsigned int timeout = 0; /* XXX decide on a reasonable value */
1143 unsigned int buf_size = 0;
1145 - printerr(1, "doing downcall\n");
1146 - buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
1147 - sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
1148 + printerr(2, "doing downcall\n");
1149 + buf_size = sizeof(updata->seq) + sizeof(timeout) +
1150 + sizeof(lgd->lgd_seq_win) +
1151 + sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
1152 sizeof(context_token->length) + context_token->length;
1153 p = buf = malloc(buf_size);
1154 end = buf + buf_size;
1156 - if (WRITE_BYTES(&p, end, uid)) goto out_err;
1157 + if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
1158 /* Not setting any timeout for now: */
1159 if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1160 - if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
1161 - if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
1162 + if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
1163 + if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
1164 if (write_buffer(&p, end, context_token)) goto out_err;
1166 - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1167 + lgssd_mutex_get(lgssd_mutex_downcall);
1168 + if (write(k5_fd, buf, p - buf) < p - buf) {
1169 + lgssd_mutex_put(lgssd_mutex_downcall);
1172 + lgssd_mutex_put(lgssd_mutex_downcall);
1178 - printerr(0, "Failed to write downcall!\n");
1179 + printerr(0, "ERROR: Failed to write downcall!\n");
1184 -do_error_downcall(int k5_fd, uid_t uid, int err)
1185 +do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
1188 char *p = buf, *end = buf + 1024;
1189 @@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid,
1191 printerr(1, "doing error downcall\n");
1193 - if (WRITE_BYTES(&p, end, uid)) goto out_err;
1194 + if (WRITE_BYTES(&p, end, seq)) goto out_err;
1195 if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1196 /* use seq_win = 0 to indicate an error: */
1197 if (WRITE_BYTES(&p, end, zero)) goto out_err;
1198 - if (WRITE_BYTES(&p, end, err)) goto out_err;
1199 + if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
1200 + if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
1202 - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1203 + lgssd_mutex_get(lgssd_mutex_downcall);
1204 + if (write(k5_fd, buf, p - buf) < p - buf) {
1205 + lgssd_mutex_put(lgssd_mutex_downcall);
1208 + lgssd_mutex_put(lgssd_mutex_downcall);
1211 printerr(0, "Failed to write error downcall!\n");
1217 * Create an RPC connection and establish an authenticated
1218 * gss context with a server.
1219 @@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
1226 +int do_negotiation(struct lustre_gss_data *lgd,
1227 + gss_buffer_desc *gss_token,
1228 + struct lustre_gss_init_res *gr,
1231 + char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
1232 + struct lgssd_ioctl_param param;
1233 + struct passwd *pw;
1235 + char outbuf[8192];
1239 + pw = getpwuid(lgd->lgd_uid);
1241 + printerr(0, "no uid %u in local user database\n",
1246 + param.version = GSSD_INTERFACE_VERSION;
1247 + param.uuid = lgd->lgd_uuid;
1248 + param.lustre_svc = lgd->lgd_lustre_svc;
1249 + param.uid = lgd->lgd_uid;
1250 + param.gid = pw->pw_gid;
1251 + param.send_token_size = gss_token->length;
1252 + param.send_token = (char *) gss_token->value;
1253 + param.reply_buf_size = sizeof(outbuf);
1254 + param.reply_buf = outbuf;
1256 + fd = open(file, O_RDWR);
1258 + printerr(0, "can't open file %s\n", file);
1262 + ret = write(fd, ¶m, sizeof(param));
1264 + if (ret != sizeof(param)) {
1265 + printerr(0, "lustre ioctl err: %d\n", strerror(errno));
1269 + if (param.status) {
1271 + printerr(0, "status: %d (%s)\n",
1272 + param.status, strerror((int)param.status));
1273 + if (param.status == -ETIMEDOUT) {
1274 + /* kernel return -ETIMEDOUT means the rpc timedout,
1275 + * we should notify the caller to reinitiate the
1276 + * gss negotiation, by return -ERESTART
1278 + lgd->lgd_rpc_err = -ERESTART;
1279 + lgd->lgd_gss_err = 0;
1281 + lgd->lgd_rpc_err = param.status;
1282 + lgd->lgd_gss_err = 0;
1286 + p = (unsigned int *)outbuf;
1288 + gr->gr_major = *p++;
1289 + gr->gr_minor = *p++;
1290 + gr->gr_win = *p++;
1292 + gr->gr_ctx.length = *p++;
1293 + gr->gr_ctx.value = malloc(gr->gr_ctx.length);
1294 + memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
1295 + p += (((gr->gr_ctx.length + 3) & ~3) / 4);
1297 + gr->gr_token.length = *p++;
1298 + gr->gr_token.value = malloc(gr->gr_token.length);
1299 + memcpy(gr->gr_token.value, p, gr->gr_token.length);
1300 + p += (((gr->gr_token.length + 3) & ~3) / 4);
1302 + printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
1303 + gr->gr_ctx.length, gr->gr_token.length);
1309 +int gssd_refresh_lgd(struct lustre_gss_data *lgd)
1311 + struct lustre_gss_init_res gr;
1312 + gss_buffer_desc *recv_tokenp, send_token;
1313 + OM_uint32 maj_stat, min_stat, call_stat, ret_flags;
1315 + /* GSS context establishment loop. */
1316 + memset(&gr, 0, sizeof(gr));
1317 + recv_tokenp = GSS_C_NO_BUFFER;
1320 + /* print the token we just received */
1321 + if (recv_tokenp != GSS_C_NO_BUFFER) {
1322 + printerr(3, "The received token length %d\n",
1323 + recv_tokenp->length);
1324 + print_hexl(3, recv_tokenp->value, recv_tokenp->length);
1327 + maj_stat = gss_init_sec_context(&min_stat,
1332 + lgd->lgd_req_flags,
1334 + NULL, /* channel */
1336 + NULL, /* used mech */
1339 + NULL); /* time rec */
1341 + if (recv_tokenp != GSS_C_NO_BUFFER) {
1342 + gss_release_buffer(&min_stat, &gr.gr_token);
1343 + recv_tokenp = GSS_C_NO_BUFFER;
1345 + if (maj_stat != GSS_S_COMPLETE &&
1346 + maj_stat != GSS_S_CONTINUE_NEEDED) {
1347 + pgsserr("gss_init_sec_context", maj_stat, min_stat,
1351 + if (send_token.length != 0) {
1352 + memset(&gr, 0, sizeof(gr));
1354 + /* print the token we are about to send */
1355 + printerr(3, "token being sent length %d\n",
1356 + send_token.length);
1357 + print_hexl(3, send_token.value, send_token.length);
1359 + call_stat = do_negotiation(lgd, &send_token, &gr, 0);
1360 + gss_release_buffer(&min_stat, &send_token);
1362 + if (call_stat != 0 ||
1363 + (gr.gr_major != GSS_S_COMPLETE &&
1364 + gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
1365 + printerr(0, "call stat %d, major stat 0x%x\n",
1366 + (int)call_stat, gr.gr_major);
1370 + if (gr.gr_ctx.length != 0) {
1371 + if (lgd->lgd_rmt_ctx.value)
1372 + gss_release_buffer(&min_stat,
1373 + &lgd->lgd_rmt_ctx);
1374 + lgd->lgd_rmt_ctx = gr.gr_ctx;
1376 + if (gr.gr_token.length != 0) {
1377 + if (maj_stat != GSS_S_CONTINUE_NEEDED)
1379 + recv_tokenp = &gr.gr_token;
1383 + /* GSS_S_COMPLETE => check gss header verifier,
1384 + * usually checked in gss_validate
1386 + if (maj_stat == GSS_S_COMPLETE) {
1387 + lgd->lgd_established = 1;
1388 + lgd->lgd_seq_win = gr.gr_win;
1392 + /* End context negotiation loop. */
1393 + if (!lgd->lgd_established) {
1394 + if (gr.gr_token.length != 0)
1395 + gss_release_buffer(&min_stat, &gr.gr_token);
1397 + printerr(0, "context negotiation failed\n");
1401 + printerr(2, "successfully refreshed lgd\n");
1406 +int gssd_create_lgd(struct clnt_info *clp,
1407 + struct lustre_gss_data *lgd,
1408 + struct lgssd_upcall_data *updata,
1411 + gss_buffer_desc sname;
1412 + OM_uint32 maj_stat, min_stat;
1415 + lgd->lgd_established = 0;
1416 + lgd->lgd_lustre_svc = updata->svc;
1417 + lgd->lgd_uid = updata->uid;
1418 + lgd->lgd_uuid = updata->obd;
1420 + switch (authtype) {
1421 + case AUTHTYPE_KRB5:
1422 + lgd->lgd_mech = (gss_OID) &krb5oid;
1423 + lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1425 + case AUTHTYPE_SPKM3:
1426 + lgd->lgd_mech = (gss_OID) &spkm3oid;
1427 + /* XXX sec.req_flags = GSS_C_ANON_FLAG;
1428 + * Need a way to switch....
1430 + lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1433 + printerr(0, "Invalid authentication type (%d)\n", authtype);
1437 + lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
1438 + lgd->lgd_ctx = GSS_C_NO_CONTEXT;
1439 + lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
1440 + lgd->lgd_seq_win = 0;
1442 + sname.value = clp->servicename;
1443 + sname.length = strlen(clp->servicename);
1445 + maj_stat = gss_import_name(&min_stat, &sname,
1446 + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
1448 + if (maj_stat != GSS_S_COMPLETE) {
1449 + pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
1453 + retval = gssd_refresh_lgd(lgd);
1455 + if (lgd->lgd_name != GSS_C_NO_NAME)
1456 + gss_release_name(&min_stat, &lgd->lgd_name);
1458 + if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
1459 + gss_release_cred(&min_stat, &lgd->lgd_cred);
1466 +void gssd_free_lgd(struct lustre_gss_data *lgd)
1468 + gss_buffer_t token = GSS_C_NO_BUFFER;
1469 + OM_uint32 maj_stat, min_stat;
1471 + if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
1474 + maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
1478 +int construct_service_name(struct clnt_info *clp,
1479 + struct lgssd_upcall_data *ud)
1481 + const int buflen = 256;
1482 + char name[buflen];
1484 + if (clp->servicename) {
1485 + free(clp->servicename);
1486 + clp->servicename = NULL;
1489 + if (lnet_nid2hostname(ud->nid, name, buflen))
1492 + clp->servicename = malloc(32 + strlen(name));
1493 + if (!clp->servicename) {
1494 + printerr(0, "can't alloc memory\n");
1497 + sprintf(clp->servicename, "%s@%s",
1498 + ud->svc == LUSTRE_GSS_SVC_MDS ?
1499 + GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
1501 + printerr(2, "constructed servicename: %s\n", clp->servicename);
1506 * this code uses the userland rpcsec gss library to create a krb5
1507 @@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
1509 handle_krb5_upcall(struct clnt_info *clp)
1512 - CLIENT *rpc_clnt = NULL;
1513 - AUTH *auth = NULL;
1514 - struct authgss_private_data pd;
1515 - gss_buffer_desc token;
1517 + gss_buffer_desc token = { 0, NULL };
1518 + struct lgssd_upcall_data updata;
1519 + struct lustre_gss_data lgd;
1520 char **credlist = NULL;
1524 - printerr(1, "handling krb5 upcall\n");
1525 + printerr(2, "handling krb5 upcall\n");
1528 - token.value = NULL;
1529 - memset(&pd, 0, sizeof(struct authgss_private_data));
1530 + memset(&lgd, 0, sizeof(lgd));
1531 + lgd.lgd_rpc_err = -EPERM; /* default error code */
1533 - if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
1534 - printerr(0, "WARNING: failed reading uid from krb5 "
1535 + read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
1536 + if (read_rc < 0) {
1537 + printerr(0, "WARNING: failed reading from krb5 "
1538 "upcall pipe: %s\n", strerror(errno));
1541 + } else if (read_rc != sizeof(updata)) {
1542 + printerr(0, "upcall data mismatch: length %d, expect %d\n",
1543 + read_rc, sizeof(updata));
1545 + /* the sequence number must be the first field. if read >= 4
1546 + * bytes then we know at least sequence is fine, try to send
1547 + * error notification nicely.
1550 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1554 + /* FIXME temporary fix, do this before fork.
1555 + * in case of errors could have memory leak!!!
1557 + if (updata.uid == 0) {
1558 + if (gssd_get_krb5_machine_cred_list(&credlist)) {
1559 + printerr(0, "ERROR: Failed to obtain machine "
1561 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1566 + /* fork child process */
1569 + printerr(0, "can't fork: %s\n", strerror(errno));
1570 + do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1572 + } else if (pid > 0) {
1573 + printerr(2, "forked child process: %d\n", pid);
1577 + printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
1578 + updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
1580 + if (updata.svc != LUSTRE_GSS_SVC_MDS &&
1581 + updata.svc != LUSTRE_GSS_SVC_OSS) {
1582 + printerr(0, "invalid svc %d\n", updata.svc);
1583 + lgd.lgd_rpc_err = -EPROTO;
1584 + goto out_return_error;
1586 + updata.obd[sizeof(updata.obd)-1] = '\0';
1588 + if (construct_service_name(clp, &updata)) {
1589 + printerr(0, "failed to construct service name\n");
1590 + goto out_return_error;
1594 + if (updata.uid == 0) {
1598 * Get a list of credential cache names and try each
1599 * of them until one works or we've tried them all
1602 if (gssd_get_krb5_machine_cred_list(&credlist)) {
1603 - printerr(0, "WARNING: Failed to obtain machine "
1604 - "credentials for connection to "
1605 - "server %s\n", clp->servername);
1606 - goto out_return_error;
1607 + printerr(0, "ERROR: Failed to obtain machine "
1608 + "credentials for %s\n", clp->servicename);
1609 + goto out_return_error;
1612 for (ccname = credlist; ccname && *ccname; ccname++) {
1613 gssd_setup_krb5_machine_gss_ccache(*ccname);
1614 - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1615 - AUTHTYPE_KRB5)) == 0) {
1616 + if ((gssd_create_lgd(clp, &lgd, &updata,
1617 + AUTHTYPE_KRB5)) == 0) {
1622 printerr(2, "WARNING: Failed to create krb5 context "
1623 "for user with uid %d with credentials "
1624 - "cache %s for server %s\n",
1625 - uid, *ccname, clp->servername);
1626 + "cache %s for service %s\n",
1627 + updata.uid, *ccname, clp->servicename);
1629 gssd_free_krb5_machine_cred_list(credlist);
1631 - printerr(0, "WARNING: Failed to create krb5 context "
1632 + printerr(0, "ERROR: Failed to create krb5 context "
1633 "for user with uid %d with any "
1634 - "credentials cache for server %s\n",
1635 - uid, clp->servername);
1636 + "credentials cache for service %s\n",
1637 + updata.uid, clp->servicename);
1638 goto out_return_error;
1642 /* Tell krb5 gss which credentials cache to use */
1643 - gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
1644 + gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
1646 - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1647 - AUTHTYPE_KRB5)) != 0) {
1648 + if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
1649 printerr(0, "WARNING: Failed to create krb5 context "
1650 - "for user with uid %d for server %s\n",
1651 - uid, clp->servername);
1652 + "for user with uid %d for service %s\n",
1653 + updata.uid, clp->servicename);
1654 goto out_return_error;
1658 - if (!authgss_get_private_data(auth, &pd)) {
1659 - printerr(0, "WARNING: Failed to obtain authentication "
1660 - "data for user with uid %d for server %s\n",
1661 - uid, clp->servername);
1662 - goto out_return_error;
1665 - if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
1666 + if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
1667 printerr(0, "WARNING: Failed to serialize krb5 context for "
1668 - "user with uid %d for server %s\n",
1669 - uid, clp->servername);
1670 + "user with uid %d for service %s\n",
1671 + updata.uid, clp->servicename);
1672 goto out_return_error;
1675 - do_downcall(clp->krb5_fd, uid, &pd, &token);
1676 + printerr(1, "refreshed: %u@%s for %s\n",
1677 + updata.uid, updata.obd, clp->servicename);
1678 + do_downcall(clp->krb5_fd, &updata, &lgd, &token);
1683 - if (pd.pd_ctx_hndl.length != 0)
1684 - authgss_free_private_data(&pd);
1686 - AUTH_DESTROY(auth);
1688 - clnt_destroy(rpc_clnt);
1691 + gssd_free_lgd(&lgd);
1692 + exit(0); /* i'm child process */
1695 - do_error_downcall(clp->krb5_fd, uid, -1);
1696 + do_error_downcall(clp->krb5_fd, updata.seq,
1697 + lgd.lgd_rpc_err, lgd.lgd_gss_err);
1701 @@ -775,6 +1059,7 @@ out_return_error:
1703 handle_spkm3_upcall(struct clnt_info *clp)
1707 CLIENT *rpc_clnt = NULL;
1709 @@ -826,4 +1111,5 @@ out:
1711 do_error_downcall(clp->spkm3_fd, uid, -1);
1715 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c nfs-utils-1.0.11/utils/gssd/gss_util.c
1716 --- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c 2007-02-21 21:50:03.000000000 -0700
1717 +++ nfs-utils-1.0.11/utils/gssd/gss_util.c 2008-01-02 18:11:38.000000000 -0700
1719 #ifdef HAVE_COM_ERR_H
1720 #include <com_err.h>
1722 +#include "lsupport.h"
1724 /* Global gssd_credentials handle */
1725 -gss_cred_id_t gssd_creds;
1726 +gss_cred_id_t gssd_cred_mds;
1727 +gss_cred_id_t gssd_cred_oss;
1728 +int gssd_cred_mds_valid = 0;
1729 +int gssd_cred_oss_valid = 0;
1731 +char *mds_local_realm = NULL;
1732 +char *oss_local_realm = NULL;
1734 gss_OID g_mechOid = GSS_C_NULL_OID;;
1736 @@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
1737 display_status_2(msg, maj_stat, min_stat, mech);
1741 -gssd_acquire_cred(char *server_name)
1743 +int extract_realm_name(gss_buffer_desc *name, char **realm)
1748 + sname = malloc(name->length + 1);
1750 + printerr(0, "out of memory\n");
1754 + memcpy(sname, name->value, name->length);
1755 + sname[name->length] = '\0';
1756 + printerr(1, "service principal: %s\n", sname);
1758 + c = strchr(sname, '@');
1760 + printerr(2, "no realm found in principal, use default\n");
1761 + *realm = strdup(this_realm);
1763 + printerr(0, "failed to duplicate default realm\n");
1768 + *realm = strdup(c);
1770 + printerr(0, "failed to duplicated realm\n");
1780 +int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
1781 + char **local_realm, int *valid)
1783 gss_buffer_desc name;
1784 gss_name_t target_name;
1785 u_int32_t maj_stat, min_stat;
1786 u_int32_t ignore_maj_stat, ignore_min_stat;
1787 + gss_OID name_type;
1788 gss_buffer_desc pbuf;
1792 name.value = (void *)server_name;
1793 name.length = strlen(server_name);
1795 @@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
1797 if (maj_stat != GSS_S_COMPLETE) {
1798 pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
1803 + maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
1804 + if (maj_stat != GSS_S_COMPLETE) {
1805 + pgsserr(0, maj_stat, min_stat, g_mechOid);
1808 + if (extract_realm_name(&name, local_realm))
1811 maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
1812 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
1813 - &gssd_creds, NULL, NULL);
1814 + cred, NULL, NULL);
1816 if (maj_stat != GSS_S_COMPLETE) {
1817 pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
1818 @@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
1819 ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
1826 ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
1828 - return (maj_stat == GSS_S_COMPLETE);
1829 + if (maj_stat != GSS_S_COMPLETE)
1834 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
1836 + if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
1837 + &mds_local_realm, &gssd_cred_mds_valid)) {
1842 + if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
1843 + &oss_local_realm, &gssd_cred_oss_valid)) {
1848 + if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
1849 + printerr(0, "can't obtain both mds & oss creds, exit\n");
1853 + if (gssd_cred_mds_valid)
1854 + printerr(0, "Ready to serve Lustre MDS in realm %s\n",
1855 + mds_local_realm ? mds_local_realm : "N/A");
1856 + if (gssd_cred_oss_valid)
1857 + printerr(0, "Ready to serve Lustre OSS in realm %s\n",
1858 + oss_local_realm ? oss_local_realm : "N/A");
1863 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
1865 + switch (lustre_svc) {
1866 + case LUSTRE_GSS_SVC_MDS:
1867 + if (!gssd_cred_mds_valid) {
1868 + printerr(0, "ERROR: service cred for mds not ready\n");
1871 + printerr(2, "select mds service cred\n");
1872 + return gssd_cred_mds;
1873 + case LUSTRE_GSS_SVC_OSS:
1874 + if (!gssd_cred_oss_valid) {
1875 + printerr(0, "ERROR: service cred for oss not ready\n");
1878 + printerr(2, "select oss service cred\n");
1879 + return gssd_cred_oss;
1881 + printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
1887 int gssd_check_mechs(void)
1888 @@ -249,3 +361,42 @@ out:
1892 +/*********************************
1893 + * FIXME should be in krb5_util.c
1894 + *********************************/
1896 +#include "krb5_util.h"
1898 +/* realm of this node */
1899 +char *this_realm = NULL;
1901 +int gssd_get_local_realm(void)
1903 + krb5_context context = NULL;
1904 + krb5_error_code code;
1907 + if (this_realm != NULL)
1910 + code = krb5_init_context(&context);
1912 + printerr(0, "ERROR: get default realm: init ctx: %s\n",
1913 + error_message(code));
1917 + code = krb5_get_default_realm(context, &this_realm);
1919 + printerr(0, "ERROR: get default realm: %s\n",
1920 + error_message(code));
1925 + printerr(1, "Local realm: %s\n", this_realm);
1927 + krb5_free_context(context);
1931 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h nfs-utils-1.0.11/utils/gssd/gss_util.h
1932 --- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h 2007-02-21 21:50:03.000000000 -0700
1933 +++ nfs-utils-1.0.11/utils/gssd/gss_util.h 2008-01-02 18:11:38.000000000 -0700
1935 #define _GSS_UTIL_H_
1938 -#include <rpc/rpc.h>
1939 #include "write_bytes.h"
1942 extern gss_cred_id_t gssd_creds;
1944 -int gssd_acquire_cred(char *server_name);
1945 void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
1946 const gss_OID mech);
1947 int gssd_check_mechs(void);
1948 +int gssd_get_local_realm(void);
1950 #endif /* _GSS_UTIL_H_ */
1951 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c nfs-utils-1.0.11/utils/gssd/krb5_util.c
1952 --- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c 2008-01-02 17:22:48.000000000 -0700
1953 +++ nfs-utils-1.0.11/utils/gssd/krb5_util.c 2008-01-02 18:11:38.000000000 -0700
1955 #include <rpc/rpc.h>
1956 #include <sys/types.h>
1957 #include <sys/stat.h>
1958 +#include <sys/utsname.h>
1959 #include <sys/socket.h>
1960 #include <arpa/inet.h>
1962 +#include <unistd.h>
1971 #include <gssapi/gssapi_krb5.h>
1974 -#include <rpc/auth_gss.h>
1977 #include "err_util.h"
1978 @@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
1979 int num_krb5_enctypes = 0;
1980 krb5_enctype *krb5_enctypes = NULL;
1982 +/* credential expire time in advance */
1983 +unsigned long machine_cred_expire_advance = 300; /* 5 mins */
1985 /*==========================*/
1986 /*=== Internal routines ===*/
1987 /*==========================*/
1988 @@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
1989 static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
1990 static int gssd_get_single_krb5_cred(krb5_context context,
1991 krb5_keytab kt, struct gssd_k5_kt_princ *ple);
1992 -static int gssd_have_realm_ple(void *realm);
1993 static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
1997 + * convenient macros, these perhaps need further cleanup
2001 +#define KEYTAB_ENTRY_MATCH(kte, name) \
2003 + (kte).principal->data[0].length == (sizeof(name)-1) && \
2004 + strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0 \
2006 +#define KRB5_FREE_UNPARSED_NAME(ctx, name) \
2007 + krb5_free_unparsed_name((ctx), (name));
2008 +#define KRB5_STRDUP(str) \
2009 + strndup((str).data, (str).length)
2010 +#define KRB5_STRCMP(str, name) \
2012 + (str)->length != strlen(name) || \
2013 + strncmp((str)->data, (name), (str)->length) != 0 \
2015 +#define KRB5_STRCASECMP(str, name) \
2017 + (str)->length != strlen(name) || \
2018 + strncasecmp((str)->data, (name), (str)->length) != 0 \
2021 +#else /* !HAVE_KRB5 */
2023 +#define KEYTAB_ENTRY_MATCH(kte, name) \
2025 + strlen((kte).principal->name.name_string.val[0]) == \
2026 + (sizeof(name)-1) && \
2027 + strncmp(kte.principal->name.name_string.val[0], (name), \
2028 + sizeof(name)-1) == 0 \
2030 +#define KRB5_FREE_UNPARSED_NAME(ctx, name) \
2032 +#define KRB5_STRDUP(str) \
2034 +#define KRB5_STRCMP(str, name) \
2035 + strcmp((str), (name))
2036 +#define KRB5_STRCASECMP(str, name) \
2037 + strcmp((str), (name))
2039 +#endif /* HAVE_KRB5 */
2042 * Called from the scandir function to weed out potential krb5
2043 * credentials cache files
2045 @@ -288,7 +337,7 @@ gssd_get_single_krb5_cred(krb5_context c
2047 memset(&my_creds, 0, sizeof(my_creds));
2049 - if (ple->ccname && ple->endtime > now) {
2050 + if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
2051 printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
2052 ple->ccname, ple->endtime);
2054 @@ -308,6 +357,12 @@ gssd_get_single_krb5_cred(krb5_context c
2055 /* set a short lifetime (for debugging only!) */
2056 printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
2057 krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
2059 + /* FIXME try to get the ticket with lifetime as long as possible,
2060 + * to work around ticket-expiry + recovery problem in cmd3-11
2063 + krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
2065 if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
2066 kt, 0, NULL, &options))) {
2067 @@ -319,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c
2068 "principal '%s' from keytab '%s'\n",
2069 error_message(code),
2070 pname ? pname : "<unparsable>", kt_name);
2072 - if (pname) krb5_free_unparsed_name(context, pname);
2074 - if (pname) free(pname);
2076 + if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
2080 @@ -372,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
2085 - * Determine if we already have a ple for the given realm
2088 - * 0 => no ple found for given realm
2089 - * 1 => found ple for given realm
2092 -gssd_have_realm_ple(void *r)
2093 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
2095 struct gssd_k5_kt_princ *ple;
2097 @@ -390,18 +433,76 @@ gssd_have_realm_ple(void *r)
2100 for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
2102 - if ((realm->length == strlen(ple->realm)) &&
2103 - (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2105 - if (strcmp(realm, ple->realm) == 0) {
2109 + if (KRB5_STRCMP(realm, ple->realm) == 0)
2115 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2118 + krb5_free_principal(kctx, ple->princ);
2122 + free(ple->ccname);
2126 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2128 + struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2129 + struct gssd_k5_kt_princ *ent = gssd_k5_kt_princ_list;
2131 + for (; ent; prev = &ent->next, ent = ent->next) {
2135 + *prev = ent->next;
2136 + gssd_free_ple(kctx, ent);
2143 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2144 + krb5_principal principal)
2146 + struct gssd_k5_kt_princ *ple;
2147 + krb5_error_code code;
2149 + ple = malloc(sizeof(*ple));
2150 + if (ple == NULL) {
2151 + printerr(0, "ERROR: could not allocate storage "
2152 + "for principal list entry\n");
2156 + memset(ple, 0, sizeof(*ple));
2158 + ple->realm = KRB5_STRDUP(principal->realm);
2159 + if (ple->realm == NULL) {
2160 + printerr(0, "ERROR: not enough memory while copying realm to "
2161 + "principal list entry\n");
2165 + code = krb5_copy_principal(kctx, principal, &ple->princ);
2167 + printerr(0, "ERROR: %s while copying principal "
2168 + "to principal list entry\n",
2169 + error_message(code));
2175 + gssd_free_ple(kctx, ple);
2180 * Process the given keytab file and create a list of principals we
2181 * might use to perform mount operations.
2182 @@ -445,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co
2184 printerr(2, "Processing keytab entry for principal '%s'\n",
2187 - if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
2188 - (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
2189 - GSSD_SERVICE_NAME_LEN) == 0) &&
2191 - if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
2192 - (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
2193 - GSSD_SERVICE_NAME_LEN) == 0) &&
2196 - (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
2197 - printerr(2, "We will use this entry (%s)\n", pname);
2198 - ple = malloc(sizeof(struct gssd_k5_kt_princ));
2199 - if (ple == NULL) {
2200 - printerr(0, "ERROR: could not allocate storage "
2201 - "for principal list entry\n");
2203 - krb5_free_unparsed_name(context, pname);
2210 - /* These will be filled in later */
2212 - ple->ccname = NULL;
2216 - strndup(kte.principal->realm.data,
2217 - kte.principal->realm.length))
2219 - strdup(kte.principal->realm))
2222 - printerr(0, "ERROR: %s while copying realm to "
2223 - "principal list entry\n",
2224 - "not enough memory");
2226 - krb5_free_unparsed_name(context, pname);
2233 - if ((code = krb5_copy_principal(context,
2234 - kte.principal, &ple->princ))) {
2235 - printerr(0, "ERROR: %s while copying principal "
2236 - "to principal list entry\n",
2237 - error_message(code));
2239 - krb5_free_unparsed_name(context, pname);
2246 - if (gssd_k5_kt_princ_list == NULL)
2247 - gssd_k5_kt_princ_list = ple;
2249 - ple->next = gssd_k5_kt_princ_list;
2250 - gssd_k5_kt_princ_list = ple;
2252 + /* mds service entry:
2253 + * - hostname and realm should match this node
2254 + * - replace existing non-mds entry of this realm
2256 + if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
2257 + krb5_principal princ = kte.principal;
2258 + krb5_data *princ_host;
2259 + struct utsname utsbuf;
2260 + struct hostent *host;
2262 + if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2263 + this_realm) != 0) {
2264 + printerr(2, "alien mds service entry, skip\n");
2268 + princ_host = krb5_princ_component(context, princ, 1);
2269 + if (princ_host == NULL) {
2270 + printerr(2, "mds service entry: no hostname in "
2271 + "principal, skip\n");
2275 + if (uname(&utsbuf)) {
2276 + printerr(2, "mds service entry: unable to get "
2277 + "UTS name, skip\n");
2280 + host = gethostbyname(utsbuf.nodename);
2281 + if (host == NULL) {
2282 + printerr(2, "mds service entry: unable to get "
2283 + "local hostname, skip\n");
2287 + if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
2288 + printerr(2, "mds service entry: hostname "
2289 + "doesn't match: %s - %.*s, skip\n",
2291 + princ_host->length, princ_host->data);
2295 + ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2297 + if (ple->fl_mds) {
2298 + printerr(2,"mds service entry: found a"
2299 + "duplicated one, it's like a "
2300 + "mis-configuration, skip\n");
2304 + gssd_remove_ple(context, ple);
2305 + printerr(2, "mds service entry: replace an "
2306 + "existed non-mds one\n");
2308 + } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2309 + ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2311 + if (ple->fl_mds || ple->fl_root) {
2312 + printerr(2, "root entry: found a "
2313 + "existed %s entry, skip\n",
2314 + ple->fl_mds ? "mds" : "root");
2318 + gssd_remove_ple(context, ple);
2319 + printerr(2, "root entry: replace an existed "
2320 + "non-mds non-root one\n");
2325 printerr(2, "We will NOT use this entry (%s)\n",
2330 - krb5_free_unparsed_name(context, pname);
2335 + /* construct ple */
2336 + printerr(2, "We will use this entry (%s)\n", pname);
2337 + ple = gssd_create_ple(context, kte.principal);
2338 + if (ple == NULL) {
2339 + KRB5_FREE_UNPARSED_NAME(context, pname);
2343 + /* add proper flags */
2344 + if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2346 + else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2350 + if (gssd_k5_kt_princ_list == NULL)
2351 + gssd_k5_kt_princ_list = ple;
2353 + ple->next = gssd_k5_kt_princ_list;
2354 + gssd_k5_kt_princ_list = ple;
2357 + KRB5_FREE_UNPARSED_NAME(context, pname);
2360 if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
2361 @@ -636,6 +761,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
2362 printerr(2, "getting credentials for client with uid %u for "
2363 "server %s\n", uid, servername);
2364 memset(buf, 0, sizeof(buf));
2366 if (gssd_find_existing_krb5_ccache(uid, &d)) {
2367 snprintf(buf, sizeof(buf), "FILE:%s/%s",
2368 ccachedir, d->d_name);
2369 @@ -696,7 +822,7 @@ gssd_refresh_krb5_machine_creds(void)
2373 - printerr(1, "Using keytab file '%s'\n", keytabfile);
2374 + printerr(2, "Using keytab file '%s'\n", keytabfile);
2376 if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
2377 printerr(0, "ERROR: %s while resolving keytab '%s'\n",
2378 @@ -711,12 +837,12 @@ gssd_refresh_krb5_machine_creds(void)
2379 if (gssd_k5_kt_princ_list == NULL) {
2380 printerr(0, "ERROR: No usable keytab entries found in "
2381 "keytab '%s'\n", keytabfile);
2382 - printerr(0, "Do you have a valid keytab entry for "
2383 - "%s/<your.host>@<YOUR.REALM> in "
2384 + printerr(0, "You must have a valid keytab entry for "
2385 + "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
2386 + "and %s@<YOUR.REALM> on client nodes, in "
2387 "keytab file %s ?\n",
2388 - GSSD_SERVICE_NAME, keytabfile);
2389 - printerr(0, "Continuing without (machine) credentials "
2390 - "- nfs4 mounts with Kerberos will fail\n");
2391 + GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
2396 @@ -866,6 +992,7 @@ gssd_destroy_krb5_machine_creds(void)
2397 krb5_free_context(context);
2401 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2403 * this routine obtains a credentials handle via gss_acquire_cred()
2404 @@ -921,7 +1048,9 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2407 #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2412 * Obtain supported enctypes from kernel.
2413 * Set defaults if info is not available.
2414 @@ -988,3 +1117,4 @@ gssd_obtain_kernel_krb5_info(void)
2419 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h nfs-utils-1.0.11/utils/gssd/krb5_util.h
2420 --- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h 2008-01-02 17:22:48.000000000 -0700
2421 +++ nfs-utils-1.0.11/utils/gssd/krb5_util.h 2008-01-02 18:11:38.000000000 -0700
2423 struct gssd_k5_kt_princ {
2424 struct gssd_k5_kt_princ *next;
2425 krb5_principal princ;
2426 + unsigned int fl_root:1,
2430 krb5_timestamp endtime;
2431 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2432 void gssd_obtain_kernel_krb5_info(void);
2435 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2436 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2439 #endif /* KRB5_UTIL_H */
2440 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am nfs-utils-1.0.11/utils/gssd/Makefile.am
2441 --- nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am 2007-02-21 21:50:03.000000000 -0700
2442 +++ nfs-utils-1.0.11/utils/gssd/Makefile.am 2008-01-02 18:10:29.000000000 -0700
2444 ## Process this file with automake to produce Makefile.in
2446 -man8_MANS = gssd.man svcgssd.man
2451 -sbin_PREFIXED = gssd svcgssd
2452 -sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err
2453 +sbin_PREFIXED = lgssd lsvcgssd
2454 +sbin_PROGRAMS = $(sbin_PREFIXED)
2455 sbin_SCRIPTS = gss_destroy_creds
2458 - gss_destroy_creds \
2464 @@ -21,13 +15,15 @@ COMMON_SRCS = \
2482 @@ -38,13 +34,12 @@ gssd_SOURCES = \
2486 -gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
2487 -gssd_LDFLAGS = $(KRBLDFLAGS)
2488 +lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
2489 +lgssd_LDFLAGS = $(KRBLDFLAGS)
2491 -gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2492 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2493 +lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
2495 -svcgssd_SOURCES = \
2496 +lsvcgssd_SOURCES = \
2500 @@ -55,20 +50,11 @@ svcgssd_SOURCES = \
2505 - ../../support/nfs/libnfs.a \
2506 - $(RPCSECGSS_LIBS) -lnfsidmap \
2509 -svcgssd_LDFLAGS = $(KRBLDFLAGS)
2511 -svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2512 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2513 +lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
2515 -gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
2516 +lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
2518 -gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2519 - $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2520 +lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
2522 MAINTAINERCLEANFILES = Makefile.in
2524 @@ -92,23 +78,3 @@ uninstall-hook:
2528 -# XXX This makes some assumptions about what automake does.
2529 -# XXX But there is no install-man-hook or install-man-local.
2530 -install-man: install-man8 install-man-links
2531 -uninstall-man: uninstall-man8 uninstall-man-links
2534 - (cd $(DESTDIR)$(man8dir) && \
2535 - for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
2536 - inst=`echo $$m | sed -e 's/man$$/8/'`; \
2537 - rm -f $(RPCPREFIX)$$inst ; \
2538 - $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
2541 -uninstall-man-links:
2542 - (cd $(DESTDIR)$(man8dir) && \
2543 - for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
2544 - inst=`echo $$m | sed -e 's/man$$/8/'`; \
2545 - rm -f $(RPCPREFIX)$$inst ; \
2548 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c nfs-utils-1.0.11/utils/gssd/svcgssd.c
2549 --- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c 2007-02-21 21:50:03.000000000 -0700
2550 +++ nfs-utils-1.0.11/utils/gssd/svcgssd.c 2008-01-02 18:11:38.000000000 -0700
2552 #include <sys/types.h>
2553 #include <sys/stat.h>
2554 #include <sys/socket.h>
2555 -#include <rpc/rpc.h>
2563 -#include <nfsidmap.h>
2564 -#include "nfslib.h"
2565 +#include <dirent.h>
2566 #include "svcgssd.h"
2567 #include "gss_util.h"
2568 #include "err_util.h"
2569 +#include "lsupport.h"
2574 + DIR *dir = opendir("/proc/self/fd");
2575 + if (dir != NULL) {
2576 + int dfd = dirfd(dir);
2579 + while ((d = readdir(dir)) != NULL) {
2581 + long n = strtol(d->d_name, &endp, 10);
2582 + if (*endp != '\0' && n >= min && n != dfd)
2587 + int fd = sysconf(_SC_OPEN_MAX);
2588 + while (--fd >= min)
2594 * mydaemon creates a pipe between the partent and child
2595 @@ -140,6 +161,7 @@ void
2598 /* destroy krb5 machine creds */
2599 + cleanup_mapping();
2600 printerr(1, "exiting on signal %d\n", signal);
2603 @@ -155,7 +177,7 @@ sig_hup(int signal)
2605 usage(char *progname)
2607 - fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
2608 + fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o]\n",
2612 @@ -166,9 +188,8 @@ main(int argc, char *argv[])
2616 - int rpc_verbosity = 0;
2617 - int idmap_verbosity = 0;
2619 + int must_srv_mds = 0, must_srv_oss = 0;
2620 extern char *optarg;
2623 @@ -177,17 +198,19 @@ main(int argc, char *argv[])
2628 - idmap_verbosity++;
2648 @@ -201,34 +224,18 @@ main(int argc, char *argv[])
2651 initerr(progname, verbosity, fg);
2652 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
2653 - authgss_set_debug_level(rpc_verbosity);
2655 - if (rpc_verbosity > 0)
2656 - printerr(0, "Warning: rpcsec_gss library does not "
2657 - "support setting debug level\n");
2659 -#ifdef HAVE_NFS4_SET_DEBUG
2660 - nfs4_set_debug(idmap_verbosity, NULL);
2662 - if (idmap_verbosity > 0)
2663 - printerr(0, "Warning: your nfsidmap library does not "
2664 - "support setting debug level\n");
2667 if (gssd_check_mechs() != 0) {
2668 printerr(0, "ERROR: Problem with gssapi library\n");
2675 - signal(SIGINT, sig_die);
2676 - signal(SIGTERM, sig_die);
2677 - signal(SIGHUP, sig_hup);
2679 - if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
2680 + if (gssd_get_local_realm()) {
2681 + printerr(0, "ERROR: Can't get Local Kerberos realm\n");
2685 + if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
2686 printerr(0, "unable to obtain root (machine) credentials\n");
2687 printerr(0, "do you have a keytab entry for "
2688 "nfs/<your.host>@<YOUR.REALM> in "
2689 @@ -237,9 +244,23 @@ main(int argc, char *argv[])
2696 + * XXX: There is risk of memory leak for missing call
2697 + * cleanup_mapping() for SIGKILL and SIGSTOP.
2699 + signal(SIGINT, sig_die);
2700 + signal(SIGTERM, sig_die);
2701 + signal(SIGHUP, sig_hup);
2707 + gssd_init_unique(GSSD_SVC);
2710 + cleanup_mapping();
2711 printerr(0, "gssd_run returned!\n");
2714 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h nfs-utils-1.0.11/utils/gssd/svcgssd.h
2715 --- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h 2007-02-21 21:50:03.000000000 -0700
2716 +++ nfs-utils-1.0.11/utils/gssd/svcgssd.h 2008-01-02 18:11:38.000000000 -0700
2718 #include <sys/queue.h>
2719 #include <gssapi/gssapi.h>
2721 -void handle_nullreq(FILE *f);
2722 -void gssd_run(void);
2723 +int handle_nullreq(FILE *f);
2724 +void svcgssd_run(void);
2725 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
2726 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
2728 -#define GSSD_SERVICE_NAME "nfs"
2729 +extern char *mds_local_realm;
2730 +extern char *oss_local_realm;
2732 +#define GSSD_SERVICE_NAME "lustre"
2735 +#define GSSD_SERVICE_MDS "lustre_mds"
2736 +#define GSSD_SERVICE_OSS "lustre_oss"
2737 +#define LUSTRE_ROOT_NAME "lustre_root"
2738 +#define LUSTRE_ROOT_NAMELEN 11
2740 #endif /* _RPC_SVCGSSD_H_ */
2741 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c
2742 --- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c 2007-02-21 21:50:03.000000000 -0700
2743 +++ nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c 2008-01-02 18:11:38.000000000 -0700
2748 +/* For nanosleep() */
2751 #include "svcgssd.h"
2752 #include "err_util.h"
2755 + * nfs4 in-kernel cache implementation make upcall failed directly
2756 + * if there's no listener detected. so here we should keep the init
2757 + * channel file open as possible as we can.
2759 + * unfortunately the proc doesn't support dir change notification.
2760 + * and when an entry get unlinked, we only got POLLIN event once,
2761 + * it's the only oppotunity we can close the file and startover.
2770 struct pollfd pollfd;
2771 + struct timespec halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
2773 -#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
2774 +#define NULLRPC_FILE "/proc/net/rpc/auth.sptlrpc.init/channel"
2776 - f = fopen(NULLRPC_FILE, "rw");
2779 - printerr(0, "failed to open %s: %s\n",
2780 - NULLRPC_FILE, strerror(errno));
2783 - pollfd.fd = fileno(f);
2784 - pollfd.events = POLLIN;
2788 + while (f == NULL) {
2789 + f = fopen(NULLRPC_FILE, "rw");
2791 + printerr(4, "failed to open %s: %s\n",
2792 + NULLRPC_FILE, strerror(errno));
2793 + nanosleep(&halfsec, NULL);
2795 + printerr(1, "successfully open %s\n",
2800 + pollfd.fd = fileno(f);
2801 + pollfd.events = POLLIN;
2804 - printerr(1, "entering poll\n");
2805 - ret = poll(&pollfd, 1, -1);
2806 + ret = poll(&pollfd, 1, 1000);
2808 - printerr(1, "leaving poll\n");
2811 - if (save_err != EINTR)
2812 - printerr(0, "error return from poll: %s\n",
2813 - strerror(save_err));
2814 + printerr(0, "error return from poll: %s\n",
2815 + strerror(save_err));
2818 } else if (ret == 0) {
2819 - /* timeout; shouldn't happen. */
2820 + printerr(3, "poll timeout\n");
2823 printerr(0, "bug: unexpected poll return %d\n",
2827 - if (pollfd.revents & POLLIN)
2828 - handle_nullreq(f);
2829 + if (pollfd.revents & POLLIN) {
2830 + if (handle_nullreq(f) < 0) {
2838 diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c
2839 --- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c 2007-02-21 21:50:03.000000000 -0700
2840 +++ nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c 2008-01-02 18:11:38.000000000 -0700
2843 #include <sys/param.h>
2844 #include <sys/stat.h>
2845 -#include <rpc/rpc.h>
2853 -#include <nfsidmap.h>
2856 #include "svcgssd.h"
2857 #include "gss_util.h"
2858 #include "err_util.h"
2859 #include "context.h"
2860 #include "cacheio.h"
2861 +#include "lsupport.h"
2863 extern char * mech2file(gss_OID mech);
2864 -#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
2865 -#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel"
2866 +#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel"
2867 +#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.sptlrpc.init/channel"
2869 #define TOKEN_BUF_SIZE 8192
2875 - gid_t cr_groups[NGROUPS];
2876 + uint32_t cr_remote;
2877 + uint32_t cr_usr_root;
2878 + uint32_t cr_usr_mds;
2880 + uid_t cr_mapped_uid;
2885 @@ -70,11 +72,10 @@ do_svc_downcall(gss_buffer_desc *out_han
2886 gss_OID mech, gss_buffer_desc *context_token)
2893 - printerr(1, "doing downcall\n");
2894 + printerr(2, "doing downcall\n");
2895 if ((fname = mech2file(mech)) == NULL)
2897 f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
2898 @@ -87,11 +88,12 @@ do_svc_downcall(gss_buffer_desc *out_han
2899 qword_printhex(f, out_handle->value, out_handle->length);
2900 /* XXX are types OK for the rest of this? */
2901 qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
2902 + qword_printint(f, cred->cr_remote);
2903 + qword_printint(f, cred->cr_usr_root);
2904 + qword_printint(f, cred->cr_usr_mds);
2905 + qword_printint(f, cred->cr_mapped_uid);
2906 qword_printint(f, cred->cr_uid);
2907 qword_printint(f, cred->cr_gid);
2908 - qword_printint(f, cred->cr_ngroups);
2909 - for (i=0; i < cred->cr_ngroups; i++)
2910 - qword_printint(f, cred->cr_groups[i]);
2911 qword_print(f, fname);
2912 qword_printhex(f, context_token->value, context_token->length);
2914 @@ -120,7 +122,7 @@ send_response(FILE *f, gss_buffer_desc *
2918 - printerr(1, "sending null reply\n");
2919 + printerr(2, "sending null reply\n");
2921 qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
2922 qword_addhex(&bp, &blen, in_token->value, in_token->length);
2923 @@ -160,6 +162,7 @@ send_response(FILE *f, gss_buffer_desc *
2924 #define rpcsec_gsserr_credproblem 13
2925 #define rpcsec_gsserr_ctxproblem 14
2929 add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
2931 @@ -183,7 +186,9 @@ add_supplementary_groups(char *secname,
2939 get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
2941 @@ -249,7 +254,9 @@ out_free:
2949 print_hexl(int pri, unsigned char *cp, int length)
2951 @@ -286,12 +293,149 @@ print_hexl(int pri, unsigned char *cp, i
2959 +get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
2960 + lnet_nid_t nid, uint32_t lustre_svc)
2962 + u_int32_t maj_stat, min_stat;
2963 + gss_buffer_desc name;
2964 + char *sname, *host, *realm;
2965 + const int namebuf_size = 512;
2966 + char namebuf[namebuf_size];
2968 + gss_OID name_type = GSS_C_NO_OID;
2969 + struct passwd *pw;
2971 + cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
2972 + cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
2974 + maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
2975 + if (maj_stat != GSS_S_COMPLETE) {
2976 + pgsserr("get_ids: gss_display_name",
2977 + maj_stat, min_stat, mech);
2980 + if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
2981 + !(sname = calloc(name.length + 1, 1))) {
2982 + printerr(0, "WARNING: get_ids: error allocating %d bytes "
2983 + "for sname\n", name.length + 1);
2984 + gss_release_buffer(&min_stat, &name);
2987 + memcpy(sname, name.value, name.length);
2988 + gss_release_buffer(&min_stat, &name);
2990 + if (lustre_svc == LUSTRE_GSS_SVC_MDS)
2991 + lookup_mapping(sname, nid, &cred->cr_mapped_uid);
2993 + cred->cr_mapped_uid = -1;
2995 + realm = strchr(sname, '@');
2999 + host = strchr(sname, '/');
3003 + if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
3004 + printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
3008 + /* 1. check host part */
3010 + if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
3011 + printerr(0, "ERROR: failed to resolve hostname for "
3012 + "%s/%s@%s from %016llx\n",
3013 + sname, host, realm, nid);
3017 + if (strcasecmp(host, namebuf)) {
3018 + printerr(0, "ERROR: %s/%s@s claimed hostname doesn't "
3019 + "match %s, nid %016llx\n", sname, host, realm,
3024 + if (!strcmp(sname, GSSD_SERVICE_MDS)) {
3025 + printerr(0, "ERROR: "GSSD_SERVICE_MDS"@%s from %016llx "
3026 + "doesn't bind with hostname\n",
3027 + realm ? realm : "", nid);
3032 + /* 2. check realm */
3035 + cred->cr_remote = (mds_local_realm != NULL);
3037 + printerr(0, "ERROR: %s%s%s have no realm name\n",
3038 + sname, host ? "/" : "", host ? "host" : "");
3042 + if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) {
3043 + cred->cr_remote = 1;
3045 + if (cred->cr_mapped_uid == -1)
3046 + printerr(0, "ERROR: %s from %016llx is remote but "
3047 + "without mapping\n", sname, nid);
3048 + /* mapped, skip user checking */
3052 + /* 3. check user */
3053 + if (!(pw = getpwnam(sname))) {
3054 + /* map lustre_root/lustre_mds to root user, which is subject
3055 + * to further mapping by root-squash in kernel. */
3056 + if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
3058 + cred->cr_usr_root = 1;
3059 + } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
3061 + cred->cr_usr_mds = 1;
3063 + if (cred->cr_mapped_uid == -1) {
3064 + printerr(0, "ERROR: invalid user, %s/%s@%s "
3065 + "from %016llx\n", sname, host,
3070 + printerr(2, "user %s from %016llx is mapped to %u\n",
3071 + sname, nid, cred->cr_mapped_uid);
3073 + /* note: a mapped local user will go to here too */
3074 + cred->cr_uid = pw->pw_uid;
3075 + printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
3078 + printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
3079 + lustre_svc_name[lustre_svc], sname,
3080 + host ? "/" : "", host ? host : "", realm, nid);
3087 +typedef struct gss_union_ctx_id_t {
3088 + gss_OID mech_type;
3089 + gss_ctx_id_t internal_ctx_id;
3090 +} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
3093 + * return -1 only if we detect error during reading from upcall channel,
3094 + * all other cases return 0.
3097 handle_nullreq(FILE *f) {
3098 - /* XXX initialize to a random integer to reduce chances of unnecessary
3099 - * invalidation of existing ctx's on restarting svcgssd. */
3100 - static u_int32_t handle_seq = 0;
3101 + uint64_t handle_seq;
3102 char in_tok_buf[TOKEN_BUF_SIZE];
3103 char in_handle_buf[15];
3104 char out_handle_buf[15];
3105 @@ -303,10 +447,13 @@ handle_nullreq(FILE *f) {
3106 ignore_out_tok = {.value = NULL},
3107 /* XXX isn't there a define for this?: */
3108 null_token = {.value = NULL};
3109 + uint32_t lustre_svc;
3111 u_int32_t ret_flags;
3112 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
3113 gss_name_t client_name;
3114 gss_OID mech = GSS_C_NO_OID;
3115 + gss_cred_id_t svc_cred;
3116 u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0;
3117 u_int32_t ignore_min_stat;
3118 struct svc_cred cred;
3119 @@ -314,25 +461,31 @@ handle_nullreq(FILE *f) {
3120 static int lbuflen = 0;
3123 - printerr(1, "handling null request\n");
3124 + printerr(2, "handling null request\n");
3126 if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
3127 printerr(0, "WARNING: handle_nullreq: "
3128 "failed reading request\n");
3135 + qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
3136 + qword_get(&cp, (char *) &nid, sizeof(nid));
3137 + qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
3138 + printerr(2, "handling req: svc %u, nid %016llx, idx %llx\n",
3139 + lustre_svc, nid, handle_seq);
3141 in_handle.length = (size_t) qword_get(&cp, in_handle.value,
3142 sizeof(in_handle_buf));
3143 - printerr(2, "in_handle: \n");
3144 - print_hexl(2, in_handle.value, in_handle.length);
3145 + printerr(3, "in_handle: \n");
3146 + print_hexl(3, in_handle.value, in_handle.length);
3148 in_tok.length = (size_t) qword_get(&cp, in_tok.value,
3149 sizeof(in_tok_buf));
3150 - printerr(2, "in_tok: \n");
3151 - print_hexl(2, in_tok.value, in_tok.length);
3152 + printerr(3, "in_tok: \n");
3153 + print_hexl(3, in_tok.value, in_tok.length);
3155 if (in_tok.length < 0) {
3156 printerr(0, "WARNING: handle_nullreq: "
3157 @@ -352,7 +505,13 @@ handle_nullreq(FILE *f) {
3158 memcpy(&ctx, in_handle.value, in_handle.length);
3161 - maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
3162 + svc_cred = gssd_select_svc_cred(lustre_svc);
3164 + printerr(0, "no service credential for svc %u\n", lustre_svc);
3168 + maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
3169 &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
3170 &mech, &out_tok, &ret_flags, NULL, NULL);
3172 @@ -370,7 +529,8 @@ handle_nullreq(FILE *f) {
3173 maj_stat, min_stat, mech);
3176 - if (get_ids(client_name, mech, &cred)) {
3178 + if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
3179 /* get_ids() prints error msg */
3180 maj_stat = GSS_S_BAD_NAME; /* XXX ? */
3181 gss_release_name(&ignore_min_stat, &client_name);
3182 @@ -378,10 +538,8 @@ handle_nullreq(FILE *f) {
3184 gss_release_name(&ignore_min_stat, &client_name);
3187 /* Context complete. Pass handle_seq in out_handle to use
3188 * for context lookup in the kernel. */
3190 out_handle.length = sizeof(handle_seq);
3191 memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
3193 @@ -405,8 +563,7 @@ out:
3194 free(ctx_token.value);
3195 if (out_tok.value != NULL)
3196 gss_release_buffer(&ignore_min_stat, &out_tok);
3197 - printerr(1, "finished handling null request\n");
3202 if (ctx != GSS_C_NO_CONTEXT)
3203 diff -Nrup nfs-utils-1.0.11.lustre/utils/Makefile.am nfs-utils-1.0.11/utils/Makefile.am
3204 --- nfs-utils-1.0.11.lustre/utils/Makefile.am 2007-02-21 21:50:03.000000000 -0700
3205 +++ nfs-utils-1.0.11/utils/Makefile.am 2008-01-02 18:10:29.000000000 -0700
3237 MAINTAINERCLEANFILES = Makefile.in