Whamcloud - gitweb
land b_colibri_devel on HEAD:
[fs/lustre-release.git] / lustre / utils / gss / nfs-utils-1.0.11-lustre.diff
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,
5         RELEASE=$withval,
6         RELEASE=1)
7         AC_SUBST(RELEASE)
8 -AC_ARG_WITH(statedir,
9 -       [  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]],
10 -       statedir=$withval,
11 -       statedir=/var/lib/nfs)
12 -       AC_SUBST(statedir)
13 -AC_ARG_WITH(statduser,
14 -       [AC_HELP_STRING([--with-statduser=rpcuser],
15 -                        [statd to run under @<:@rpcuser or nobody@:>@]
16 -       )],
17 -       statduser=$withval,
18 -       if test "x$cross_compiling" = "xno"; then
19 -               if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
20 -                       statduser=rpcuser
21 -               else
22 -                       statduser=nobody
23 -               fi
24 -       else
25 -               statduser=nobody
26 -       fi)
27 -       AC_SUBST(statduser)
28 -AC_ARG_ENABLE(nfsv3,
29 -       [AC_HELP_STRING([--enable-nfsv3],
30 -                        [enable support for NFSv3 @<:@default=yes@:>@])],
31 -       enable_nfsv3=$enableval,
32 -       enable_nfsv3=yes)
33 -       if test "$enable_nfsv3" = yes; then
34 -               AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in])
35 -       else
36 -               enable_nfsv3=
37 -       fi
38 -       AC_SUBST(enable_nfsv3)
39 -AC_ARG_ENABLE(nfsv4,
40 -       [AC_HELP_STRING([--enable-nfsv4],
41 -                        [enable support for NFSv4 @<:@default=yes@:>@])],
42 -       enable_nfsv4=$enableval,
43 -       enable_nfsv4=yes)
44 -       if test "$enable_nfsv4" = yes; then
45 -               AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in])
46 -               IDMAPD=idmapd
47 -       else
48 -               enable_nfsv4=
49 -               IDMAPD=
50 -       fi
51 -       AC_SUBST(IDMAPD)
52 -       AC_SUBST(enable_nfsv4)
53 -       AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
54  AC_ARG_ENABLE(gss,
55         [AC_HELP_STRING([--enable-gss],
56                          [enable support for rpcsec_gss @<:@default=yes@:>@])],
57         enable_gss=$enableval,
58         enable_gss=yes)
59         if test "$enable_gss" = yes; then
60 -               AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in])
61 -               GSSD=gssd
62 -               SVCGSSD=svcgssd
63 +               GSSD=lgssd
64 +               SVCGSSD=lsvcgssd
65         else
66                 enable_gss=
67                 GSSD=
68 @@ -82,38 +35,6 @@ AC_ARG_ENABLE(gss,
69         AC_SUBST(SVCGSSD)
70         AC_SUBST(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,
75 -       kprefix=)
76 -       AC_SUBST(kprefix)
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,
81 -       secure_statd=no)
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.])
84 -       fi
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,
90 -       enable_rquotad=yes)
91 -       if test "$enable_rquotad" = yes; then
92 -               RQUOTAD=rquotad
93 -       else
94 -               RQUOTAD=
95 -       fi
96 -       AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"])
97 -
98 -AC_ARG_ENABLE(mount,
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,
102 -       enable_mount=no)
103 -       AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
104  
105  # Check whether user wants TCP wrappers support
106  AC_TCP_WRAPPERS
107 @@ -156,50 +77,15 @@ AC_CHECK_FUNC(connect, ,
108                  AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL))
109  
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])
121 -      ]
122 -     )
123 -    PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
124 -    fi
125 -
126 -fi
127 -if test "$knfsd_cv_glibc2" = no; then
128 -    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
129 -fi
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)
133  AC_SUBST(LIBSOCKET)
134  AC_SUBST(LIBCRYPT)
135  AC_SUBST(LIBBSD)
136  AC_SUBST(LIBBLKID)
137  
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]),)
146 -
147    dnl Check for Kerberos V5
148    AC_KERBEROS_V5
149 -
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)
155 -
156  fi
157  
158  dnl *************************************************************
159 @@ -311,33 +197,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
160  
161  AC_CONFIG_FILES([
162         Makefile
163 -       linux-nfs/Makefile
164 -       support/Makefile
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
173 -       tools/Makefile
174 -       tools/getiversion/Makefile
175 -       tools/locktest/Makefile
176 -       tools/nlmtest/Makefile
177 -       tools/rpcdebug/Makefile
178 -       tools/rpcgen/Makefile
179         utils/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])
192  AC_OUTPUT
193  
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
197 @@ -1,6 +1,6 @@
198  ## Process this file with automake to produce Makefile.in
199  
200 -SUBDIRS = tools support utils linux-nfs
201 +SUBDIRS = utils
202  
203  MAINTAINERCLEANFILES = Makefile.in
204  
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
209                 return -1;
210         while (*bp == ' ') bp++;
211         *bpp = bp;
212 -       *dest = '\0';
213 +// why should we clear *dest???
214 +//     *dest = '\0';
215         return len;
216  }
217  
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
221 @@ -33,11 +33,14 @@
222  #include <syslog.h>
223  #include <string.h>
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"
230 +
231 +#ifdef _NEW_BUILD_
232 +# include "lgss_utils.h"
233 +#else
234 +# include "gss_util.h"
235 +# include "gss_oids.h"
236 +# include "err_util.h"
237 +#endif
238  #include "context.h"
239  
240  int
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
244 @@ -31,8 +31,6 @@
245  #ifndef _CONTEXT_H_
246  #define _CONTEXT_H_
247  
248 -#include <rpc/rpc.h>
249 -
250  /* Hopefully big enough to hold any serialized context */
251  #define MAX_CTX_LEN 4096
252  
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
256 @@ -43,8 +43,13 @@
257  #ifdef HAVE_COM_ERR_H
258  #include <com_err.h>
259  #endif
260 -#include "err_util.h"
261 -#include "gss_oids.h"
262 +
263 +#ifdef _NEW_BUILD_
264 +# include "lgss_utils.h"
265 +#else
266 +# include "err_util.h"
267 +# include "gss_oids.h"
268 +#endif
269  #include "write_bytes.h"
270  
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
275 @@ -41,11 +41,7 @@
276  #include <syslog.h>
277  #include <string.h>
278  #include <errno.h>
279 -#include "gss_util.h"
280 -#include "gss_oids.h"
281 -#include "err_util.h"
282 -#include "context.h"
283 -
284 +#include <stdint.h>
285  #include <krb5.h>
286  #include <gssapi/gssapi.h>
287  #ifndef OM_uint64
288 @@ -53,6 +49,16 @@ typedef uint64_t OM_uint64;
289  #endif
290  #include <gssapi/gssapi_krb5.h>
291  
292 +#ifdef _NEW_BUILD_
293 +# include "lgss_utils.h"
294 +#else
295 +# include "gss_util.h"
296 +# include "gss_oids.h"
297 +# include "err_util.h"
298 +#endif
299 +#include "write_bytes.h"
300 +#include "context.h"
301 +
302  static int
303  write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
304  {
305 @@ -354,6 +360,7 @@ static int
306  prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
307                             gss_buffer_desc *buf)
308  {
309 +       static int constant_two = 2;
310         char *p, *end;
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;
315  
316         /* Version 2 */
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;
320  
321         if (lctx->initiate)
322 @@ -387,7 +394,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
323         if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
324  
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;
330  #ifdef HAVE_HEIMDAL
331 @@ -415,8 +422,8 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
332                 }
333                 numkeys = 3;
334         }
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
343                         goto out_err;
344  
345                 /* Kc */
346 -               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
347 -                               &derived_key,
348 -                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
349 -                       goto out_err;
350 -               if (write_bytes(&p, end, derived_key.data,
351 -                               derived_key.length))
352 -                       goto out_err;
353 -               free(derived_key.data);
354 +               /*
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
358 +                */
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))
362 +                               goto out_err;
363 +               } else {
364 +                       if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
365 +                                       &derived_key,
366 +                                       KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
367 +                               goto out_err;
368 +                       if (write_bytes(&p, end, derived_key.data,
369 +                                       derived_key.length))
370 +                               goto out_err;
371 +                       free(derived_key.data);
372 +               }
373         } else {
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
377                 else
378                         keyptr = &lctx->cfx_kd.ctx_key;
379  
380 +#if 0
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;
387                 }
388 +#else
389 +               /* FIXME
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?
393 +                *
394 +                * Here we simply use old SIGN/SEAL values until we find the
395 +                * answer.  --ericm
396 +                * FIXME
397 +                */
398 +               sign_usage = KG_USAGE_SIGN;
399 +               seal_usage = KG_USAGE_SEAL;
400 +#endif
401  
402                 /* derive and send down: Ke, Ki, and Kc */
403  
404 @@ -515,7 +547,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
405         gss_krb5_lucid_context_v1_t *lctx = 0;
406         int retcode = 0;
407  
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,
411                                                 1, &return_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
416 @@ -39,10 +39,15 @@
417  #include <errno.h>
418  #include <gssapi/gssapi.h>
419  #include <rpc/rpc.h>
420 -#include <rpc/auth_gss.h>
421 -#include "gss_util.h"
422 -#include "gss_oids.h"
423 -#include "err_util.h"
424 +
425 +#ifdef _NEW_BUILD_
426 +# include "lgss_utils.h"
427 +# include "write_bytes.h"
428 +#else
429 +# include "gss_util.h"
430 +# include "gss_oids.h"
431 +# include "err_util.h"
432 +#endif
433  #include "context.h"
434  
435  #include <krb5.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) )
439                  */
440 -               if (kctx->initiate) {
441 -                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
442 -               }
443 -               else {
444 -                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
445 -               }
446 +               if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
447                 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
448  
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
453 @@ -33,8 +33,6 @@
454  #include <syslog.h>
455  #include <string.h>
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
465 @@ -32,6 +32,8 @@
466  #include <stdarg.h>
467  #include <syslog.h>
468  #include <string.h>
469 +#include <fcntl.h>
470 +#include <ctype.h>
471  #include "err_util.h"
472  
473  static int verbosity = 0;
474 @@ -91,3 +93,40 @@ printit:
475         /* reset the buffer */
476         memset(message_buf, 0, sizeof(message_buf));
477  }
478 +
479 +void print_hexl(int pri, unsigned char *cp, int length)
480 +{
481 +       int i, j, jm;
482 +       unsigned char c;
483 +
484 +       printerr(pri, "length %d\n",length);
485 +       printerr(pri, "\n");
486 +
487 +       for (i = 0; i < length; i += 0x10) {
488 +               printerr(pri, "  %04x: ", (u_int)i);
489 +               jm = length - i;
490 +               jm = jm > 16 ? 16 : jm;
491 +
492 +               for (j = 0; j < jm; j++) {
493 +                       if ((j % 2) == 1)
494 +                               printerr(pri,"%02x ", (u_int)cp[i+j]);
495 +                       else
496 +                               printerr(pri,"%02x", (u_int)cp[i+j]);
497 +               }
498 +               for (; j < 16; j++) {
499 +                       if ((j % 2) == 1)
500 +                               printerr(pri,"   ");
501 +                       else
502 +                               printerr(pri,"  ");
503 +               }
504 +               printerr(pri," ");
505 +
506 +               for (j = 0; j < jm; j++) {
507 +                       c = cp[i+j];
508 +                       c = isprint(c) ? c : '.';
509 +                       printerr(pri,"%c", c);
510 +               }
511 +               printerr(pri,"\n");
512 +       }
513 +}
514 +
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
518 @@ -33,5 +33,6 @@
519  
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);
523  
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
528 @@ -47,6 +47,7 @@
529  #include "gssd.h"
530  #include "write_bytes.h"
531  
532 +#if 0
533  char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
534  
535  static void
536 @@ -102,3 +103,4 @@ main(int argc, char *argv[])
537         }
538         exit(0);
539  }
540 +#endif
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
544 @@ -38,9 +38,12 @@
545  
546  #include "config.h"
547  
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>
555  
556  #include <unistd.h>
557  #include <err.h>
558 @@ -48,23 +51,107 @@
559  #include <stdlib.h>
560  #include <string.h>
561  #include <signal.h>
562 +#include <errno.h>
563  #include "gssd.h"
564  #include "err_util.h"
565  #include "gss_util.h"
566  #include "krb5_util.h"
567 +#include "lsupport.h"
568  
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;
575  
576 -void
577 -sig_die(int signal)
578 +static int lgssd_create_mutex(int *semid)
579 +{
580 +       int             id;
581 +       int             arg;
582 +
583 +       id = semget(IPC_PRIVATE, 1, IPC_CREAT);
584 +       if (id == -1) {
585 +               printerr(0, "semget: %s\n", strerror(errno));
586 +               return -1;
587 +       }
588 +
589 +       arg = 1;
590 +       if (semctl(id, 0, SETVAL, arg) != 0) {
591 +               printerr(0, "semctl: %s\n", strerror(errno));
592 +               semctl(id, 1, IPC_RMID, arg);
593 +               return -1;
594 +       }
595 +
596 +       *semid = id;
597 +       return 0;
598 +}
599 +
600 +void lgssd_init_mutexs(void)
601 +{
602 +       if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
603 +               printerr(0, "can't create downcall mutex\n");
604 +               exit(1);
605 +       }
606 +}
607 +
608 +void lgssd_fini_mutexs(void)
609 +{
610 +       int     arg = 0;
611 +
612 +       if (lgssd_mutex_downcall != -1)
613 +               semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
614 +}
615 +
616 +void lgssd_mutex_get(int semid)
617 +{
618 +       struct sembuf   op[1] = { {0, -1, SEM_UNDO} };
619 +       int             rc;
620 +
621 +       rc = semop(semid, op, 1);
622 +       if (rc != 0) {
623 +               printerr(0, "exit on mutex_get err %d: %s\n",
624 +                        rc, strerror(errno));
625 +               exit(1);
626 +       }
627 +}
628 +
629 +void lgssd_mutex_put(int semid)
630  {
631 +       struct sembuf   op[1] = { {0, 1, 0} };
632 +       int             rc;
633 +
634 +       rc = semop(semid, op, 1);
635 +       if (rc != 0) {
636 +               printerr(0, "ignore mutex_put err %d: %s\n",
637 +                        rc, strerror(errno));
638 +       }
639 +}
640 +
641 +static void lgssd_cleanup(void)
642 +{
643 +       pid_t   child_pid;
644 +
645 +       /* make sure all children finished */
646 +       while (1) {
647 +               child_pid = waitpid(-1, NULL, 0);
648 +               if (child_pid < 0)
649 +                       break;
650 +
651 +               printerr(3, "cleanup: child %d terminated\n", child_pid);
652 +       }
653 +
654 +       lgssd_fini_mutexs();
655 +
656         /* destroy krb5 machine creds */
657         gssd_destroy_krb5_machine_creds();
658 +}
659 +
660 +void
661 +sig_die(int signal)
662 +{
663         printerr(1, "exiting on signal %d\n", signal);
664 +       lgssd_cleanup();
665         exit(1);
666  }
667  
668 @@ -79,7 +166,7 @@ sig_hup(int signal)
669  static void
670  usage(char *progname)
671  {
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",
674                 progname);
675         exit(1);
676  }
677 @@ -89,7 +176,6 @@ main(int argc, char *argv[])
678  {
679         int fg = 0;
680         int verbosity = 0;
681 -       int rpc_verbosity = 0;
682         int opt;
683         extern char *optarg;
684         char *progname;
685 @@ -99,18 +185,12 @@ main(int argc, char *argv[])
686                         case 'f':
687                                 fg = 1;
688                                 break;
689 -                       case 'm':
690 -                               /* Accept but ignore this. Now the default. */
691 -                               break;
692                         case 'M':
693                                 use_memcache = 1;
694                                 break;
695                         case 'v':
696                                 verbosity++;
697                                 break;
698 -                       case 'r':
699 -                               rpc_verbosity++;
700 -                               break;
701                         case 'p':
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[])
705                                 break;
706                 }
707         }
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");
712  
713         if ((progname = strrchr(argv[0], '/')))
714                 progname++;
715 @@ -142,30 +218,42 @@ main(int argc, char *argv[])
716                 progname = argv[0];
717  
718         initerr(progname, verbosity, fg);
719 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
720 -       authgss_set_debug_level(rpc_verbosity);
721 -#else
722 -        if (rpc_verbosity > 0)
723 -               printerr(0, "Warning: rpcsec_gss library does not "
724 -                           "support setting debug level\n");
725 -#endif
726  
727         if (gssd_check_mechs() != 0)
728                 errx(1, "Problem with gssapi library");
729  
730 +       if (gssd_get_local_realm())
731 +               errx(1, "get local realm");
732 +
733         if (!fg && daemon(0, 0) < 0)
734                 errx(1, "fork");
735  
736 +       /* This should be checked _after_ daemon(), because we need to own
737 +        * the undo-able semaphore by this process
738 +        */
739 +       gssd_init_unique(GSSD_CLI);
740 +
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
743 +        */
744 +       if (gssd_refresh_krb5_machine_creds())
745 +               return -1;
746 +
747         signal(SIGINT, sig_die);
748         signal(SIGTERM, sig_die);
749         signal(SIGHUP, sig_hup);
750  
751 -       /* Process keytab file and get machine credentials */
752 -       gssd_refresh_krb5_machine_creds();
753 +#if 0
754         /* Determine Kerberos information from the kernel */
755         gssd_obtain_kernel_krb5_info();
756 +#endif
757 +
758 +       lgssd_init_mutexs();
759 +
760 +       printerr(0, "lgssd initialized and ready to serve\n");
761 +       lgssd_run();
762  
763 -       gssd_run();
764 -       printerr(0, "gssd_run returned!\n");
765 -       abort();
766 +       lgssd_cleanup();
767 +       printerr(0, "lgssd exiting\n");
768 +       return 0;
769  }
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
773 @@ -48,8 +48,13 @@
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
783 +
784 +#define LUSTRE_ROOT_NAME                       "lustre_root"
785 +#define LUSTRE_ROOT_NAMELEN                    11
786  
787  /*
788   * The gss mechanisms that we can handle
789 @@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
790  
791  
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;
798  
799  TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
800 @@ -71,10 +76,6 @@ struct clnt_info {
801         char                    *dirname;
802         int                     dir_fd;
803         char                    *servicename;
804 -       char                    *servername;
805 -       int                     prog;
806 -       int                     vers;
807 -       char                    *protocol;
808         int                     krb5_fd;
809         int                     krb5_poll_index;
810         int                     spkm3_fd;
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);
818 +
819 +
820 +extern int lgssd_mutex_downcall;
821  
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);
826  
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
831 @@ -44,6 +44,10 @@
832  #include <fcntl.h>
833  #include <signal.h>
834  #include <unistd.h>
835 +/* For time() */
836 +#include <time.h>
837 +/* For waitpid() */
838 +#include <wait.h>
839  
840  #include "gssd.h"
841  #include "err_util.h"
842 @@ -94,11 +98,13 @@ scan_poll_results(int ret)
843  };
844  
845  void
846 -gssd_run()
847 +lgssd_run()
848  {
849         int                     ret;
850         struct sigaction        dn_act;
851         int                     fd;
852 +       time_t                  child_check = 0;
853 +       pid_t                   child_pid;
854  
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);
860  
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));
865 -               exit(1);
866 +                        pipefs_dir, strerror(errno));
867 +               return;
868         }
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()
872         while (1) {
873                 while (dir_changed) {
874                         dir_changed = 0;
875 +                       printerr(2, "pipefs root dir changed\n");
876                         if (update_client_list()) {
877                                 printerr(0, "ERROR: couldn't update "
878                                          "client list\n");
879 -                               exit(1);
880 +                               goto out;
881                         }
882                 }
883 +
884 +               /* every 5s cleanup possible zombies of child processes */
885 +               if (time(NULL) - child_check >= 5) {
886 +                       printerr(3, "check zombie children...\n");
887 +
888 +                       while (1) {
889 +                               child_pid = waitpid(-1, NULL, WNOHANG);
890 +                               if (child_pid <= 0)
891 +                                       break;
892 +
893 +                               printerr(2, "terminate zombie child: %d\n",
894 +                                        child_pid);
895 +                       }
896 +
897 +                       child_check = time(NULL);
898 +               }
899 +
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
902                  * timeout. */
903 @@ -139,6 +163,7 @@ gssd_run()
904                         scan_poll_results(ret);
905                 }
906         }
907 +out:
908         close(fd);
909         return;
910  }
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
914 @@ -43,7 +43,6 @@
915  #endif
916  #include "config.h"
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>
922 @@ -69,6 +68,7 @@
923  #include "gss_oids.h"
924  #include "krb5_util.h"
925  #include "context.h"
926 +#include "lsupport.h"
927  
928  /*
929   * pollarray:
930 @@ -99,86 +99,10 @@ struct pollfd * pollarray;
931  
932  int pollsize;  /* the size of pollaray (in pollfd's) */
933  
934 -/* XXX buffer problems: */
935 -static int
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];
941 -       int             nbytes;
942 -       static char     service[128];
943 -       static char     address[128];
944 -       char            program[16];
945 -       char            version[16];
946 -       char            protoname[16];
947 -       in_addr_t       inaddr;
948 -       int             fd = -1;
949 -       struct hostent  *ent = NULL;
950 -       int             numfields;
951 -
952 -       *servicename = *servername = *protocol = NULL;
953 -
954 -       if ((fd = open(info_file_name, O_RDONLY)) == -1) {
955 -               printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
956 -                        strerror(errno));
957 -               goto fail;
958 -       }
959 -       if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
960 -               goto fail;
961 -       close(fd);
962 -
963 -       numfields = sscanf(buf,"RPC server: %127s\n"
964 -                  "service: %127s %15s version %15s\n"
965 -                  "address: %127s\n"
966 -                  "protocol: %15s\n",
967 -                  dummy,
968 -                  service, program, version,
969 -                  address,
970 -                  protoname);
971 -
972 -       if (numfields == 5) {
973 -               strcpy(protoname, "tcp");
974 -       } else if (numfields != 6) {
975 -               goto fail;
976 -       }
977 -
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)))
983 -               goto fail;
984 -
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);
989 -               goto fail;
990 -       }
991 -       if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
992 -               goto fail;
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)))
996 -               goto fail;
997 -       memcpy(*servicename, buf, strlen(buf));
998 -
999 -       if (!(*protocol = strdup(protoname)))
1000 -               goto fail;
1001 -       return 0;
1002 -fail:
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);
1008 -       return -1;
1009 -}
1010 -
1011  static void
1012  destroy_client(struct clnt_info *clp)
1013  {
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);
1024         free(clp);
1025  }
1026  
1027 @@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info 
1028  {
1029         char    kname[32];
1030         char    sname[32];
1031 -       char    info_file_name[32];
1032  
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 
1036         }
1037         if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
1038                 return -1;
1039 -       snprintf(info_file_name, sizeof(info_file_name), "%s/info",
1040 -                       clp->dirname);
1041 -       if ((clp->servicename == NULL) &&
1042 -            read_service_info(info_file_name, &clp->servicename,
1043 -                               &clp->servername, &clp->prog, &clp->vers,
1044 -                               &clp->protocol))
1045 -               return -1;
1046         return 0;
1047  }
1048  
1049 @@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
1050                 }
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",
1054 +                        clp->dirname);
1055         }
1056  
1057         if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
1058 @@ -386,67 +302,106 @@ find_client(char *dirname)
1059  int
1060  update_client_list(void)
1061  {
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;
1067         int i, j;
1068  
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));
1074                 return -1;
1075         }
1076  
1077 -       j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
1078 -       if (j < 0) {
1079 -               printerr(0, "ERROR: can't scandir %s: %s\n",
1080 -                        pipefs_nfsdir, strerror(errno));
1081 -               return -1;
1082 +       snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
1083 +       if (stat(lustre_dir, &statbuf) == 0) {
1084 +               namelist[0] = &lustre_dirent;
1085 +               j = 1;
1086 +               printerr(2, "re-processing lustre directory\n");
1087 +       } else {
1088 +               namelist[0] = NULL;
1089 +               j = 0;
1090 +               printerr(2, "lustre directory not exist\n");
1091         }
1092 +
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]);
1101         }
1102  
1103 -       free(namelist);
1104 +       chdir("/");
1105         return 0;
1106  }
1107  
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 */
1115 +};
1116 +
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 */
1123 +
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 */
1130 +
1131 +        int             lgd_rpc_err;
1132 +        int             lgd_gss_err;
1133 +};
1134 +
1135  static int
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)
1140  {
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;
1144  
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;
1155  
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;
1165  
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);
1170 +               goto out_err;
1171 +       }
1172 +       lgssd_mutex_put(lgssd_mutex_downcall);
1173 +
1174         if (buf) free(buf);
1175         return 0;
1176  out_err:
1177         if (buf) free(buf);
1178 -       printerr(0, "Failed to write downcall!\n");
1179 +       printerr(0, "ERROR: Failed to write downcall!\n");
1180         return -1;
1181  }
1182  
1183  static int
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)
1186  {
1187         char    buf[1024];
1188         char    *p = buf, *end = buf + 1024;
1189 @@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, 
1190  
1191         printerr(1, "doing error downcall\n");
1192  
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;
1201  
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);
1206 +               goto out_err;
1207 +       }
1208 +       lgssd_mutex_put(lgssd_mutex_downcall);
1209         return 0;
1210  out_err:
1211         printerr(0, "Failed to write error downcall!\n");
1212         return -1;
1213  }
1214  
1215 +#if 0
1216  /*
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
1220  
1221         goto out;
1222  }
1223 +#endif
1224 +
1225 +static
1226 +int do_negotiation(struct lustre_gss_data *lgd,
1227 +                  gss_buffer_desc *gss_token,
1228 +                  struct lustre_gss_init_res *gr,
1229 +                  int timeout)
1230 +{
1231 +       char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
1232 +       struct lgssd_ioctl_param param;
1233 +       struct passwd *pw;
1234 +       int fd, ret;
1235 +       char outbuf[8192];
1236 +       unsigned int *p;
1237 +       int res;
1238 +
1239 +       pw = getpwuid(lgd->lgd_uid);
1240 +       if (!pw) {
1241 +               printerr(0, "no uid %u in local user database\n",
1242 +                        lgd->lgd_uid);
1243 +               return -1;
1244 +       }
1245 +
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;
1255 +
1256 +       fd = open(file, O_RDWR);
1257 +       if (fd < 0) {
1258 +               printerr(0, "can't open file %s\n", file);
1259 +               return -1;
1260 +       }
1261 +
1262 +       ret = write(fd, &param, sizeof(param));
1263 +
1264 +       if (ret != sizeof(param)) {
1265 +               printerr(0, "lustre ioctl err: %d\n", strerror(errno));
1266 +               close(fd);
1267 +               return -1;
1268 +       }
1269 +       if (param.status) {
1270 +               close(fd);
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
1277 +                        */
1278 +                       lgd->lgd_rpc_err = -ERESTART;
1279 +                       lgd->lgd_gss_err = 0;
1280 +               } else {
1281 +                       lgd->lgd_rpc_err = param.status;
1282 +                       lgd->lgd_gss_err = 0;
1283 +               }
1284 +               return -1;
1285 +       }
1286 +       p = (unsigned int *)outbuf;
1287 +       res = *p++;
1288 +       gr->gr_major = *p++;
1289 +       gr->gr_minor = *p++;
1290 +       gr->gr_win = *p++;
1291 +
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);
1296 +
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);
1301 +
1302 +       printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
1303 +                gr->gr_ctx.length, gr->gr_token.length);
1304 +       close(fd);
1305 +       return 0;
1306 +}
1307 +
1308 +static
1309 +int gssd_refresh_lgd(struct lustre_gss_data *lgd)
1310 +{
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;
1314 +
1315 +       /* GSS context establishment loop. */
1316 +       memset(&gr, 0, sizeof(gr));
1317 +       recv_tokenp = GSS_C_NO_BUFFER;
1318 +
1319 +       for (;;) {
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);
1325 +               }
1326 +
1327 +               maj_stat = gss_init_sec_context(&min_stat,
1328 +                                               lgd->lgd_cred,
1329 +                                               &lgd->lgd_ctx,
1330 +                                               lgd->lgd_name,
1331 +                                               lgd->lgd_mech,
1332 +                                               lgd->lgd_req_flags,
1333 +                                               0,              /* time req */
1334 +                                               NULL,           /* channel */
1335 +                                               recv_tokenp,
1336 +                                               NULL,           /* used mech */
1337 +                                               &send_token,
1338 +                                               &ret_flags,
1339 +                                               NULL);          /* time rec */
1340 +
1341 +               if (recv_tokenp != GSS_C_NO_BUFFER) {
1342 +                       gss_release_buffer(&min_stat, &gr.gr_token);
1343 +                       recv_tokenp = GSS_C_NO_BUFFER;
1344 +               }
1345 +               if (maj_stat != GSS_S_COMPLETE &&
1346 +                   maj_stat != GSS_S_CONTINUE_NEEDED) {
1347 +                       pgsserr("gss_init_sec_context", maj_stat, min_stat,
1348 +                               lgd->lgd_mech);
1349 +                       break;
1350 +               }
1351 +               if (send_token.length != 0) {
1352 +                       memset(&gr, 0, sizeof(gr));
1353 +
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);
1358 +
1359 +                       call_stat = do_negotiation(lgd, &send_token, &gr, 0);
1360 +                       gss_release_buffer(&min_stat, &send_token);
1361 +
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);
1367 +                               return -1;
1368 +                       }
1369 +
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;
1375 +                       }
1376 +                       if (gr.gr_token.length != 0) {
1377 +                               if (maj_stat != GSS_S_CONTINUE_NEEDED)
1378 +                                       break;
1379 +                               recv_tokenp = &gr.gr_token;
1380 +                       }
1381 +               }
1382 +
1383 +               /* GSS_S_COMPLETE => check gss header verifier,
1384 +                * usually checked in gss_validate
1385 +                */
1386 +               if (maj_stat == GSS_S_COMPLETE) {
1387 +                       lgd->lgd_established = 1;
1388 +                       lgd->lgd_seq_win = gr.gr_win;
1389 +                       break;
1390 +               }
1391 +       }
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);
1396 +
1397 +               printerr(0, "context negotiation failed\n");
1398 +               return -1;
1399 +       }
1400 +
1401 +       printerr(2, "successfully refreshed lgd\n");
1402 +       return 0;
1403 +}
1404  
1405 +static
1406 +int gssd_create_lgd(struct clnt_info *clp,
1407 +                   struct lustre_gss_data *lgd,
1408 +                   struct lgssd_upcall_data *updata,
1409 +                   int authtype)
1410 +{
1411 +       gss_buffer_desc         sname;
1412 +       OM_uint32               maj_stat, min_stat;
1413 +       int                     retval = -1;
1414 +
1415 +       lgd->lgd_established = 0;
1416 +       lgd->lgd_lustre_svc = updata->svc;
1417 +       lgd->lgd_uid = updata->uid;
1418 +       lgd->lgd_uuid = updata->obd;
1419 +
1420 +       switch (authtype) {
1421 +       case AUTHTYPE_KRB5:
1422 +               lgd->lgd_mech = (gss_OID) &krb5oid;
1423 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1424 +               break;
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....
1429 +                */
1430 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1431 +               break;
1432 +       default:
1433 +               printerr(0, "Invalid authentication type (%d)\n", authtype);
1434 +               return -1;
1435 +       }
1436 +
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;
1441 +
1442 +       sname.value = clp->servicename;
1443 +       sname.length = strlen(clp->servicename);
1444 +
1445 +       maj_stat = gss_import_name(&min_stat, &sname,
1446 +                                  (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
1447 +                                  &lgd->lgd_name);
1448 +       if (maj_stat != GSS_S_COMPLETE) {
1449 +               pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
1450 +               goto out_fail;
1451 +       }
1452 +
1453 +       retval = gssd_refresh_lgd(lgd);
1454 +
1455 +       if (lgd->lgd_name != GSS_C_NO_NAME)
1456 +               gss_release_name(&min_stat, &lgd->lgd_name);
1457 +
1458 +       if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
1459 +               gss_release_cred(&min_stat, &lgd->lgd_cred);
1460 +
1461 +  out_fail:
1462 +       return retval;
1463 +}
1464 +
1465 +static
1466 +void gssd_free_lgd(struct lustre_gss_data *lgd)
1467 +{
1468 +       gss_buffer_t            token = GSS_C_NO_BUFFER;
1469 +       OM_uint32               maj_stat, min_stat;
1470 +
1471 +       if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
1472 +               return;
1473 +
1474 +       maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
1475 +}
1476 +
1477 +static
1478 +int construct_service_name(struct clnt_info *clp,
1479 +                           struct lgssd_upcall_data *ud)
1480 +{
1481 +        const int buflen = 256;
1482 +        char name[buflen];
1483 +
1484 +        if (clp->servicename) {
1485 +                free(clp->servicename);
1486 +                clp->servicename = NULL;
1487 +        }
1488 +
1489 +        if (lnet_nid2hostname(ud->nid, name, buflen))
1490 +                return -1;
1491 +
1492 +        clp->servicename = malloc(32 + strlen(name));
1493 +        if (!clp->servicename) {
1494 +                printerr(0, "can't alloc memory\n");
1495 +                return -1;
1496 +        }
1497 +        sprintf(clp->servicename, "%s@%s",
1498 +                ud->svc == LUSTRE_GSS_SVC_MDS ?
1499 +               GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
1500 +                name);
1501 +        printerr(2, "constructed servicename: %s\n", clp->servicename);
1502 +        return 0;
1503 +}
1504  
1505  /*
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
1508  void
1509  handle_krb5_upcall(struct clnt_info *clp)
1510  {
1511 -       uid_t                   uid;
1512 -       CLIENT                  *rpc_clnt = NULL;
1513 -       AUTH                    *auth = NULL;
1514 -       struct authgss_private_data pd;
1515 -       gss_buffer_desc         token;
1516 +       pid_t                   pid;
1517 +       gss_buffer_desc         token = { 0, NULL };
1518 +       struct lgssd_upcall_data updata;
1519 +       struct lustre_gss_data  lgd;
1520         char                    **credlist = NULL;
1521         char                    **ccname;
1522 +       int                     read_rc;
1523  
1524 -       printerr(1, "handling krb5 upcall\n");
1525 +       printerr(2, "handling krb5 upcall\n");
1526  
1527 -       token.length = 0;
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 */
1532  
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));
1539 -               goto out;
1540 +               return;
1541 +       } else if (read_rc != sizeof(updata)) {
1542 +               printerr(0, "upcall data mismatch: length %d, expect %d\n",
1543 +                        read_rc, sizeof(updata));
1544 +
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.
1548 +                */
1549 +               if (read_rc >= 4)
1550 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1551 +               return;
1552 +       }
1553 +
1554 +       /* FIXME temporary fix, do this before fork.
1555 +        * in case of errors could have memory leak!!!
1556 +        */
1557 +       if (updata.uid == 0) {
1558 +               if (gssd_get_krb5_machine_cred_list(&credlist)) {
1559 +                       printerr(0, "ERROR: Failed to obtain machine "
1560 +                                   "credentials\n");
1561 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1562 +                       return;
1563 +               }
1564 +       }
1565 +
1566 +       /* fork child process */
1567 +       pid = fork();
1568 +       if (pid < 0) {
1569 +               printerr(0, "can't fork: %s\n", strerror(errno));
1570 +               do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1571 +               return;
1572 +       } else if (pid > 0) {
1573 +               printerr(2, "forked child process: %d\n", pid);
1574 +               return;
1575 +       }
1576 +
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);
1579 +
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;
1585 +       }
1586 +       updata.obd[sizeof(updata.obd)-1] = '\0';
1587 +
1588 +       if (construct_service_name(clp, &updata)) {
1589 +               printerr(0, "failed to construct service name\n");
1590 +               goto out_return_error;
1591         }
1592  
1593 -       if (uid == 0) {
1594 +       if (updata.uid == 0) {
1595                 int success = 0;
1596  
1597                 /*
1598                  * Get a list of credential cache names and try each
1599                  * of them until one works or we've tried them all
1600                  */
1601 +/*
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;
1610                 }
1611 +*/
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) {
1618                                 /* Success! */
1619                                 success++;
1620                                 break;
1621                         }
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);
1628                 }
1629                 gssd_free_krb5_machine_cred_list(credlist);
1630                 if (!success) {
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;
1639                 }
1640         }
1641         else {
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);
1645  
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;
1655                 }
1656         }
1657  
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;
1663 -       }
1664 -
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;
1673         }
1674  
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);
1679  
1680  out:
1681         if (token.value)
1682                 free(token.value);
1683 -       if (pd.pd_ctx_hndl.length != 0)
1684 -               authgss_free_private_data(&pd);
1685 -       if (auth)
1686 -               AUTH_DESTROY(auth);
1687 -       if (rpc_clnt)
1688 -               clnt_destroy(rpc_clnt);
1689 -       return;
1690 +
1691 +       gssd_free_lgd(&lgd);
1692 +       exit(0); /* i'm child process */
1693  
1694  out_return_error:
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);
1698         goto out;
1699  }
1700  
1701 @@ -775,6 +1059,7 @@ out_return_error:
1702  void
1703  handle_spkm3_upcall(struct clnt_info *clp)
1704  {
1705 +#if 0
1706         uid_t                   uid;
1707         CLIENT                  *rpc_clnt = NULL;
1708         AUTH                    *auth = NULL;
1709 @@ -826,4 +1111,5 @@ out:
1710  out_return_error:
1711         do_error_downcall(clp->spkm3_fd, uid, -1);
1712         goto out;
1713 +#endif
1714  }
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
1718 @@ -87,9 +87,16 @@
1719  #ifdef HAVE_COM_ERR_H
1720  #include <com_err.h>
1721  #endif
1722 +#include "lsupport.h"
1723  
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;
1730 +
1731 +char *mds_local_realm = NULL;
1732 +char *oss_local_realm = NULL;
1733  
1734  gss_OID g_mechOid = GSS_C_NULL_OID;;
1735  
1736 @@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
1737         display_status_2(msg, maj_stat, min_stat, mech);
1738  }
1739  
1740 -int
1741 -gssd_acquire_cred(char *server_name)
1742 +static
1743 +int extract_realm_name(gss_buffer_desc *name, char **realm)
1744 +{
1745 +        char *sname, *c;
1746 +       int   rc = 0;
1747 +
1748 +        sname = malloc(name->length + 1);
1749 +        if (!sname) {
1750 +                printerr(0, "out of memory\n");
1751 +                return -ENOMEM;
1752 +        }
1753 +
1754 +        memcpy(sname, name->value, name->length);
1755 +        sname[name->length] = '\0';
1756 +        printerr(1, "service principal: %s\n", sname);
1757 +
1758 +        c = strchr(sname, '@');
1759 +        if (!c) {
1760 +               printerr(2, "no realm found in principal, use default\n");
1761 +               *realm = strdup(this_realm);
1762 +                if (!*realm) {
1763 +                        printerr(0, "failed to duplicate default realm\n");
1764 +                        rc = -ENOMEM;
1765 +                }
1766 +        } else {
1767 +                c++;
1768 +                *realm = strdup(c);
1769 +                if (!*realm) {
1770 +                        printerr(0, "failed to duplicated realm\n");
1771 +                        rc = -ENOMEM;
1772 +                }
1773 +        }
1774 +        free(sname);
1775 +
1776 +        return rc;
1777 +}
1778 +
1779 +static
1780 +int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
1781 +                     char **local_realm, int *valid)
1782  {
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;
1789  
1790 +       *valid = 0;
1791 +
1792         name.value = (void *)server_name;
1793         name.length = strlen(server_name);
1794  
1795 @@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
1796  
1797         if (maj_stat != GSS_S_COMPLETE) {
1798                 pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
1799 -               return (FALSE);
1800 +               return -1;
1801 +       }
1802 +
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);
1806 +               return -1;
1807         }
1808 +       if (extract_realm_name(&name, local_realm))
1809 +               return -1;
1810  
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);
1815  
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,
1820                                                              &pbuf);
1821                 }
1822 -       }
1823 +       } else
1824 +               *valid = 1;
1825  
1826         ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
1827  
1828 -       return (maj_stat == GSS_S_COMPLETE);
1829 +       if (maj_stat != GSS_S_COMPLETE)
1830 +               return -1;
1831 +       return 0;
1832 +}
1833 +
1834 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
1835 +{
1836 +        if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
1837 +                              &mds_local_realm, &gssd_cred_mds_valid)) {
1838 +                if (must_srv_mds)
1839 +                        return -1;
1840 +        }
1841 +
1842 +        if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
1843 +                              &oss_local_realm, &gssd_cred_oss_valid)) {
1844 +                if (must_srv_oss)
1845 +                        return -1;
1846 +        }
1847 +
1848 +        if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
1849 +                printerr(0, "can't obtain both mds & oss creds, exit\n");
1850 +                return -1;
1851 +        }
1852 +
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");
1859 +
1860 +        return 0;
1861 +}
1862 +
1863 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
1864 +{
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");
1869 +                        return NULL;
1870 +                }
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");
1876 +                        return NULL;
1877 +                }
1878 +               printerr(2, "select oss service cred\n");
1879 +                return gssd_cred_oss;
1880 +        default:
1881 +                printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
1882 +        }
1883 +
1884 +        return NULL;
1885  }
1886  
1887  int gssd_check_mechs(void)
1888 @@ -249,3 +361,42 @@ out:
1889         return retval;
1890  }
1891  
1892 +/*********************************
1893 + * FIXME should be in krb5_util.c
1894 + *********************************/
1895 +
1896 +#include "krb5_util.h"
1897 +
1898 +/* realm of this node */
1899 +char *this_realm = NULL;
1900 +
1901 +int gssd_get_local_realm(void)
1902 +{
1903 +       krb5_context context = NULL;
1904 +       krb5_error_code code;
1905 +       int retval = -1;
1906 +
1907 +       if (this_realm != NULL)
1908 +               return 0;
1909 +
1910 +       code = krb5_init_context(&context);
1911 +       if (code) {
1912 +               printerr(0, "ERROR: get default realm: init ctx: %s\n",
1913 +                        error_message(code));
1914 +               goto out;
1915 +       }
1916 +
1917 +       code = krb5_get_default_realm(context, &this_realm);
1918 +       if (code) {
1919 +               printerr(0, "ERROR: get default realm: %s\n",
1920 +                        error_message(code));
1921 +               goto out;
1922 +       }
1923 +       retval = 0;
1924 +
1925 +       printerr(1, "Local realm: %s\n", this_realm);
1926 +out:
1927 +       krb5_free_context(context);
1928 +       return retval;
1929 +}
1930 +
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
1934 @@ -32,14 +32,14 @@
1935  #define _GSS_UTIL_H_
1936  
1937  #include <stdlib.h>
1938 -#include <rpc/rpc.h>
1939  #include "write_bytes.h"
1940  
1941 +char *this_realm;
1942  extern gss_cred_id_t   gssd_creds;
1943  
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);
1949  
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
1954 @@ -99,12 +99,15 @@
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>
1961  
1962 +#include <unistd.h>
1963  #include <stdio.h>
1964  #include <stdlib.h>
1965  #include <string.h>
1966 +#include <netdb.h>
1967  #include <dirent.h>
1968  #include <fcntl.h>
1969  #include <errno.h>
1970 @@ -114,7 +117,6 @@
1971  #include <gssapi/gssapi_krb5.h>
1972  #endif
1973  #include <krb5.h>
1974 -#include <rpc/auth_gss.h>
1975  
1976  #include "gssd.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;
1981  
1982 +/* credential expire time in advance */
1983 +unsigned long machine_cred_expire_advance = 300; /* 5 mins */
1984 +
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,
1994                 char *kt_name);
1995  
1996  /*
1997 + * convenient macros, these perhaps need further cleanup
1998 + */
1999 +#ifdef HAVE_KRB5
2000 +
2001 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
2002 +       (                                                                      \
2003 +        (kte).principal->data[0].length == (sizeof(name)-1) &&                \
2004 +        strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0   \
2005 +       )
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)                                                \
2011 +       (                                                                      \
2012 +        (str)->length != strlen(name) ||                                      \
2013 +        strncmp((str)->data, (name), (str)->length) != 0                      \
2014 +       )
2015 +#define KRB5_STRCASECMP(str, name)                                            \
2016 +       (                                                                      \
2017 +        (str)->length != strlen(name) ||                                      \
2018 +        strncasecmp((str)->data, (name), (str)->length) != 0                  \
2019 +       )
2020 +
2021 +#else /* !HAVE_KRB5 */
2022 +
2023 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
2024 +       (                                                                      \
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                                          \
2029 +       )
2030 +#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                    \
2031 +               free(pname);
2032 +#define KRB5_STRDUP(str)                                                      \
2033 +               strdup(str)
2034 +#define KRB5_STRCMP(str, name)                                                \
2035 +               strcmp((str), (name))
2036 +#define KRB5_STRCASECMP(str, name)                                            \
2037 +               strcmp((str), (name))
2038 +
2039 +#endif /* HAVE_KRB5 */
2040 +
2041 +/*
2042   * Called from the scandir function to weed out potential krb5
2043   * credentials cache files
2044   *
2045 @@ -288,7 +337,7 @@ gssd_get_single_krb5_cred(krb5_context c
2046  
2047         memset(&my_creds, 0, sizeof(my_creds));
2048  
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);
2053                 code = 0;
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);
2058 +#else
2059 +       /* FIXME try to get the ticket with lifetime as long as possible,
2060 +        * to work around ticket-expiry + recovery problem in cmd3-11
2061 +        * remove this!!!
2062 +        */
2063 +       krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
2064  #endif
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);
2071 -#ifdef HAVE_KRB5
2072 -               if (pname) krb5_free_unparsed_name(context, pname);
2073 -#else
2074 -               if (pname) free(pname);
2075 -#endif
2076 +               if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
2077                 goto out;
2078         }
2079  
2080 @@ -372,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
2081         return (code);
2082  }
2083  
2084 -/*
2085 - * Determine if we already have a ple for the given realm
2086 - *
2087 - * Returns:
2088 - *     0 => no ple found for given realm
2089 - *     1 => found ple for given realm
2090 - */
2091 -static int
2092 -gssd_have_realm_ple(void *r)
2093 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
2094  {
2095         struct gssd_k5_kt_princ *ple;
2096  #ifdef HAVE_KRB5
2097 @@ -390,18 +433,76 @@ gssd_have_realm_ple(void *r)
2098  #endif
2099  
2100         for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
2101 -#ifdef HAVE_KRB5
2102 -               if ((realm->length == strlen(ple->realm)) &&
2103 -                   (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2104 -#else
2105 -               if (strcmp(realm, ple->realm) == 0) {
2106 -#endif
2107 -                   return 1;
2108 -               }
2109 +               if (KRB5_STRCMP(realm, ple->realm) == 0)
2110 +                   return ple;
2111 +       }
2112 +       return NULL;
2113 +}
2114 +
2115 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2116 +{
2117 +       if (ple->princ)
2118 +               krb5_free_principal(kctx, ple->princ);
2119 +       if (ple->realm)
2120 +               free(ple->realm);
2121 +       if (ple->ccname)
2122 +               free(ple->ccname);
2123 +       free(ple);
2124 +}
2125 +
2126 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2127 +{
2128 +       struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2129 +       struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
2130 +
2131 +       for (; ent; prev = &ent->next, ent = ent->next) {
2132 +               if (ent != ple)
2133 +                       continue;
2134 +
2135 +               *prev = ent->next;
2136 +               gssd_free_ple(kctx, ent);
2137 +               return 1;
2138         }
2139         return 0;
2140  }
2141  
2142 +static
2143 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2144 +                                        krb5_principal principal)
2145 +{
2146 +       struct gssd_k5_kt_princ *ple;
2147 +       krb5_error_code          code;
2148 +
2149 +       ple = malloc(sizeof(*ple));
2150 +       if (ple == NULL) {
2151 +               printerr(0, "ERROR: could not allocate storage "
2152 +                           "for principal list entry\n");
2153 +               return NULL;
2154 +       }
2155 +
2156 +       memset(ple, 0, sizeof(*ple));
2157 +
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");
2162 +               goto err_free;
2163 +       }
2164 +
2165 +       code = krb5_copy_principal(kctx, principal, &ple->princ);
2166 +       if (code) {
2167 +               printerr(0, "ERROR: %s while copying principal "
2168 +                           "to principal list entry\n",
2169 +                        error_message(code));
2170 +               goto err_free;
2171 +       }
2172 +
2173 +       return ple;
2174 +err_free:
2175 +       gssd_free_ple(kctx, ple);
2176 +       return NULL;
2177 +}
2178 +
2179  /*
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
2183                 }
2184                 printerr(2, "Processing keytab entry for principal '%s'\n",
2185                          pname);
2186 -#ifdef HAVE_KRB5
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) &&
2190 -#else
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) &&
2194 -                             
2195 -#endif
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");
2202 -#ifdef HAVE_KRB5
2203 -                               krb5_free_unparsed_name(context, pname);
2204 -#else
2205 -                               free(pname);
2206 -#endif
2207 -                               retval = ENOMEM;
2208 -                               goto out;
2209 -                       }
2210 -                       /* These will be filled in later */
2211 -                       ple->next = NULL;
2212 -                       ple->ccname = NULL;
2213 -                       ple->endtime = 0;
2214 -                       if ((ple->realm =
2215 -#ifdef HAVE_KRB5
2216 -                               strndup(kte.principal->realm.data,
2217 -                                       kte.principal->realm.length))
2218 -#else
2219 -                               strdup(kte.principal->realm))
2220 -#endif
2221 -                                       == NULL) {
2222 -                               printerr(0, "ERROR: %s while copying realm to "
2223 -                                           "principal list entry\n",
2224 -                                        "not enough memory");
2225 -#ifdef HAVE_KRB5
2226 -                               krb5_free_unparsed_name(context, pname);
2227 -#else
2228 -                               free(pname);
2229 -#endif
2230 -                               retval = ENOMEM;
2231 -                               goto out;
2232 -                       }
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));
2238 -#ifdef HAVE_KRB5
2239 -                               krb5_free_unparsed_name(context, pname);
2240 -#else
2241 -                               free(pname);
2242 -#endif
2243 -                               retval = code;
2244 -                               goto out;
2245 -                       }
2246 -                       if (gssd_k5_kt_princ_list == NULL)
2247 -                               gssd_k5_kt_princ_list = ple;
2248 -                       else {
2249 -                               ple->next = gssd_k5_kt_princ_list;
2250 -                               gssd_k5_kt_princ_list = ple;
2251 +
2252 +               /* mds service entry:
2253 +                *   - hostname and realm should match this node
2254 +                *   - replace existing non-mds entry of this realm
2255 +                */
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;
2261 +
2262 +                       if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2263 +                                           this_realm) != 0) {
2264 +                               printerr(2, "alien mds service entry, skip\n");
2265 +                               goto next;
2266 +                       }
2267 +
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");
2272 +                               goto next;
2273 +                       }
2274 +
2275 +                       if (uname(&utsbuf)) {
2276 +                               printerr(2, "mds service entry: unable to get "
2277 +                                        "UTS name, skip\n");
2278 +                               goto next;
2279 +                       }
2280 +                       host = gethostbyname(utsbuf.nodename);
2281 +                       if (host == NULL) {
2282 +                               printerr(2, "mds service entry: unable to get "
2283 +                                        "local hostname, skip\n");
2284 +                               goto next;
2285 +                       }
2286 +
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",
2290 +                                        host->h_name,
2291 +                                        princ_host->length, princ_host->data);
2292 +                               goto next;
2293 +                       }
2294 +
2295 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2296 +                       if (ple) {
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");
2301 +                                       goto next;
2302 +                               }
2303 +
2304 +                               gssd_remove_ple(context, ple);
2305 +                               printerr(2, "mds service entry: replace an "
2306 +                                        "existed non-mds one\n");
2307 +                       }
2308 +               } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2309 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2310 +                       if (ple) {
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");
2315 +                                       goto next;
2316 +                               }
2317 +
2318 +                               gssd_remove_ple(context, ple);
2319 +                               printerr(2, "root entry: replace an existed "
2320 +                                        "non-mds non-root one\n");
2321                         }
2322 -               }
2323 -               else {
2324 +               } else {
2325                         printerr(2, "We will NOT use this entry (%s)\n",
2326                                 pname);
2327 +                       goto next;
2328                 }
2329 -#ifdef HAVE_KRB5
2330 -               krb5_free_unparsed_name(context, pname);
2331 -#else
2332 -               free(pname);
2333 -#endif
2334 +
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);
2340 +                       goto out;
2341 +               }
2342 +
2343 +               /* add proper flags */
2344 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2345 +                       ple->fl_mds = 1;
2346 +               else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2347 +                       ple->fl_root = 1;
2348 +
2349 +               /* enqueue */
2350 +               if (gssd_k5_kt_princ_list == NULL)
2351 +                       gssd_k5_kt_princ_list = ple;
2352 +               else {
2353 +                       ple->next = gssd_k5_kt_princ_list;
2354 +                       gssd_k5_kt_princ_list = ple;
2355 +               }
2356 + next:
2357 +               KRB5_FREE_UNPARSED_NAME(context, pname);
2358         }
2359  
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));
2365 +
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)
2370                 goto out;
2371         }
2372  
2373 -       printerr(1, "Using keytab file '%s'\n", keytabfile);
2374 +       printerr(2, "Using keytab file '%s'\n", keytabfile);
2375  
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,
2392 +                                   keytabfile);
2393                 }
2394         }
2395  
2396 @@ -866,6 +992,7 @@ gssd_destroy_krb5_machine_creds(void)
2397         krb5_free_context(context);
2398  }
2399  
2400 +#if 0
2401  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2402  /*
2403   * this routine obtains a credentials handle via gss_acquire_cred()
2404 @@ -921,7 +1048,9 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2405         return 0;
2406  }
2407  #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2408 +#endif
2409  
2410 +#if 0
2411  /*
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)
2415                          code);
2416         }
2417  }
2418 +#endif
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
2422 @@ -10,6 +10,8 @@
2423  struct gssd_k5_kt_princ {
2424         struct gssd_k5_kt_princ *next;
2425         krb5_principal princ;
2426 +       unsigned int    fl_root:1,
2427 +                       fl_mds:1;
2428         char *ccname;
2429         char *realm;
2430         krb5_timestamp endtime;
2431 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2432  void gssd_obtain_kernel_krb5_info(void);
2433  
2434  
2435 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2436 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2437 -#endif
2438 -
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
2443 @@ -1,17 +1,11 @@
2444  ## Process this file with automake to produce Makefile.in
2445  
2446 -man8_MANS      = gssd.man svcgssd.man
2447 -
2448 -RPCPREFIX      = rpc.
2449 +RPCPREFIX      = 
2450  KPREFIX                = @kprefix@
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
2456  
2457 -EXTRA_DIST = \
2458 -       gss_destroy_creds \
2459 -       $(man8_MANS)
2460 -
2461  COMMON_SRCS = \
2462         context.c \
2463         context_mit.c \
2464 @@ -21,13 +15,15 @@ COMMON_SRCS = \
2465         gss_util.c \
2466         gss_oids.c \
2467         err_util.c \
2468 +       lsupport.c \
2469         \
2470         context.h \
2471         err_util.h \
2472         gss_oids.h \
2473 -       gss_util.h
2474 +       gss_util.h \
2475 +       lsupport.h
2476  
2477 -gssd_SOURCES = \
2478 +lgssd_SOURCES = \
2479         $(COMMON_SRCS) \
2480         gssd.c \
2481         gssd_main_loop.c \
2482 @@ -38,13 +34,12 @@ gssd_SOURCES = \
2483         krb5_util.h \
2484         write_bytes.h
2485  
2486 -gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
2487 -gssd_LDFLAGS = $(KRBLDFLAGS)
2488 +lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
2489 +lgssd_LDFLAGS = $(KRBLDFLAGS)
2490  
2491 -gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2492 -             $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2493 +lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
2494  
2495 -svcgssd_SOURCES = \
2496 +lsvcgssd_SOURCES = \
2497         $(COMMON_SRCS) \
2498         cacheio.c \
2499         svcgssd.c \
2500 @@ -55,20 +50,11 @@ svcgssd_SOURCES = \
2501         cacheio.h \
2502         svcgssd.h
2503  
2504 -svcgssd_LDADD = \
2505 -       ../../support/nfs/libnfs.a \
2506 -       $(RPCSECGSS_LIBS) -lnfsidmap \
2507 -       $(KRBLIBS)
2508 -
2509 -svcgssd_LDFLAGS = $(KRBLDFLAGS)
2510 -
2511 -svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2512 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2513 +lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
2514  
2515 -gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
2516 +lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
2517  
2518 -gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
2519 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
2520 +lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
2521  
2522  MAINTAINERCLEANFILES = Makefile.in
2523  
2524 @@ -92,23 +78,3 @@ uninstall-hook:
2525           done)
2526  
2527  
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
2532 -
2533 -install-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 ; \
2539 -         done)
2540 -
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 ; \
2546 -         done)
2547 -
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
2551 @@ -43,7 +43,6 @@
2552  #include <sys/types.h>
2553  #include <sys/stat.h>
2554  #include <sys/socket.h>
2555 -#include <rpc/rpc.h>
2556  #include <fcntl.h>
2557  #include <errno.h>
2558  
2559 @@ -54,11 +53,33 @@
2560  #include <stdlib.h>
2561  #include <string.h>
2562  #include <signal.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"
2570 +
2571 +void
2572 +closeall(int min)
2573 +{
2574 +       DIR *dir = opendir("/proc/self/fd");
2575 +       if (dir != NULL) {
2576 +               int dfd = dirfd(dir);
2577 +               struct dirent *d;
2578 +
2579 +               while ((d = readdir(dir)) != NULL) {
2580 +                       char *endp;
2581 +                       long n = strtol(d->d_name, &endp, 10);
2582 +                       if (*endp != '\0' && n >= min && n != dfd)
2583 +                               (void) close(n);
2584 +               }
2585 +               closedir(dir);
2586 +       } else {
2587 +               int fd = sysconf(_SC_OPEN_MAX);
2588 +               while (--fd >= min)
2589 +                       (void) close(fd);
2590 +       }
2591 +}
2592  
2593  /*
2594   * mydaemon creates a pipe between the partent and child
2595 @@ -140,6 +161,7 @@ void
2596  sig_die(int signal)
2597  {
2598         /* destroy krb5 machine creds */
2599 +       cleanup_mapping();
2600         printerr(1, "exiting on signal %d\n", signal);
2601         exit(1);
2602  }
2603 @@ -155,7 +177,7 @@ sig_hup(int signal)
2604  static void
2605  usage(char *progname)
2606  {
2607 -       fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
2608 +       fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o]\n",
2609                 progname);
2610         exit(1);
2611  }
2612 @@ -166,9 +188,8 @@ main(int argc, char *argv[])
2613         int get_creds = 1;
2614         int fg = 0;
2615         int verbosity = 0;
2616 -       int rpc_verbosity = 0;
2617 -       int idmap_verbosity = 0;
2618         int opt;
2619 +       int must_srv_mds = 0, must_srv_oss = 0;
2620         extern char *optarg;
2621         char *progname;
2622  
2623 @@ -177,17 +198,19 @@ main(int argc, char *argv[])
2624                         case 'f':
2625                                 fg = 1;
2626                                 break;
2627 -                       case 'i':
2628 -                               idmap_verbosity++;
2629 -                               break;
2630                         case 'n':
2631                                 get_creds = 0;
2632                                 break;
2633                         case 'v':
2634                                 verbosity++;
2635                                 break;
2636 -                       case 'r':
2637 -                               rpc_verbosity++;
2638 +                       case 'm':
2639 +                               get_creds = 1;
2640 +                               must_srv_mds = 1;
2641 +                               break;
2642 +                       case 'o':
2643 +                               get_creds = 1;
2644 +                               must_srv_oss = 1;
2645                                 break;
2646                         default:
2647                                 usage(argv[0]);
2648 @@ -201,34 +224,18 @@ main(int argc, char *argv[])
2649                 progname = argv[0];
2650  
2651         initerr(progname, verbosity, fg);
2652 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
2653 -       authgss_set_debug_level(rpc_verbosity);
2654 -#else
2655 -       if (rpc_verbosity > 0)
2656 -               printerr(0, "Warning: rpcsec_gss library does not "
2657 -                           "support setting debug level\n");
2658 -#endif
2659 -#ifdef HAVE_NFS4_SET_DEBUG
2660 -        nfs4_set_debug(idmap_verbosity, NULL);
2661 -#else
2662 -       if (idmap_verbosity > 0)
2663 -               printerr(0, "Warning: your nfsidmap library does not "
2664 -                           "support setting debug level\n");
2665 -#endif
2666  
2667         if (gssd_check_mechs() != 0) {
2668                 printerr(0, "ERROR: Problem with gssapi library\n");
2669                 exit(1);
2670         }
2671  
2672 -       if (!fg)
2673 -               mydaemon(0, 0);
2674 -
2675 -       signal(SIGINT, sig_die);
2676 -       signal(SIGTERM, sig_die);
2677 -       signal(SIGHUP, sig_hup);
2678 -
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");
2682 +               exit(1);
2683 +       }
2684 +  
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[])
2690         }
2691  
2692         if (!fg)
2693 +               mydaemon(0, 0);
2694 +
2695 +       /*
2696 +        * XXX: There is risk of memory leak for missing call
2697 +        *      cleanup_mapping() for SIGKILL and SIGSTOP.
2698 +        */
2699 +       signal(SIGINT, sig_die);
2700 +       signal(SIGTERM, sig_die);
2701 +       signal(SIGHUP, sig_hup);
2702 +
2703 +       if (!fg)
2704                 release_parent();
2705  
2706 -       gssd_run();
2707 +       gssd_init_unique(GSSD_SVC);
2708 +
2709 +       svcgssd_run();
2710 +       cleanup_mapping();
2711         printerr(0, "gssd_run returned!\n");
2712         abort();
2713  }
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
2717 @@ -35,9 +35,20 @@
2718  #include <sys/queue.h>
2719  #include <gssapi/gssapi.h>
2720  
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);
2727  
2728 -#define GSSD_SERVICE_NAME      "nfs"
2729 +extern char *mds_local_realm;
2730 +extern char *oss_local_realm;
2731 +
2732 +#define GSSD_SERVICE_NAME      "lustre"
2733 +
2734 +/* XXX */
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
2739  
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
2744 @@ -42,50 +42,72 @@
2745  #include <fcntl.h>
2746  #include <errno.h>
2747  #include <unistd.h>
2748 +/* For nanosleep() */
2749 +#include <time.h>
2750  
2751  #include "svcgssd.h"
2752  #include "err_util.h"
2753  
2754 +/*
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.
2758 + *
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.
2762 + */
2763  void
2764 -gssd_run()
2765 +svcgssd_run()
2766  {
2767         int                     ret;
2768 -       FILE                    *f;
2769 +       FILE                    *f = NULL;
2770         struct pollfd           pollfd;
2771 +       struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
2772  
2773 -#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
2774 +#define NULLRPC_FILE "/proc/net/rpc/auth.sptlrpc.init/channel"
2775  
2776 -       f = fopen(NULLRPC_FILE, "rw");
2777 -
2778 -       if (!f) {
2779 -               printerr(0, "failed to open %s: %s\n",
2780 -                        NULLRPC_FILE, strerror(errno));
2781 -               exit(1);
2782 -       }
2783 -       pollfd.fd = fileno(f);
2784 -       pollfd.events = POLLIN;
2785         while (1) {
2786                 int save_err;
2787  
2788 +               while (f == NULL) {
2789 +                       f = fopen(NULLRPC_FILE, "rw");
2790 +                       if (f == NULL) {
2791 +                               printerr(4, "failed to open %s: %s\n",
2792 +                                        NULLRPC_FILE, strerror(errno));
2793 +                               nanosleep(&halfsec, NULL);
2794 +                       } else {
2795 +                               printerr(1, "successfully open %s\n",
2796 +                                        NULLRPC_FILE);
2797 +                               break;
2798 +                       }
2799 +               }
2800 +               pollfd.fd = fileno(f);
2801 +               pollfd.events = POLLIN;
2802 +
2803                 pollfd.revents = 0;
2804 -               printerr(1, "entering poll\n");
2805 -               ret = poll(&pollfd, 1, -1);
2806 +               ret = poll(&pollfd, 1, 1000);
2807                 save_err = errno;
2808 -               printerr(1, "leaving poll\n");
2809 +
2810                 if (ret < 0) {
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));
2816 +                       fclose(f);
2817 +                       f = NULL;
2818                 } else if (ret == 0) {
2819 -                       /* timeout; shouldn't happen. */
2820 +                       printerr(3, "poll timeout\n");
2821                 } else {
2822                         if (ret != 1) {
2823                                 printerr(0, "bug: unexpected poll return %d\n",
2824                                                 ret);
2825                                 exit(1);
2826                         }
2827 -                       if (pollfd.revents & POLLIN)
2828 -                               handle_nullreq(f);
2829 +                       if (pollfd.revents & POLLIN) {
2830 +                               if (handle_nullreq(f) < 0) {
2831 +                                       fclose(f);
2832 +                                       f = NULL;
2833 +                               }
2834 +                       }
2835                 }
2836         }
2837  }
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
2841 @@ -35,7 +35,6 @@
2842  
2843  #include <sys/param.h>
2844  #include <sys/stat.h>
2845 -#include <rpc/rpc.h>
2846  
2847  #include <pwd.h>
2848  #include <stdio.h>
2849 @@ -44,25 +43,28 @@
2850  #include <string.h>
2851  #include <fcntl.h>
2852  #include <errno.h>
2853 -#include <nfsidmap.h>
2854 +#include <netdb.h>
2855  
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"
2862  
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"
2868  
2869  #define TOKEN_BUF_SIZE         8192
2870  
2871  struct svc_cred {
2872 -       uid_t   cr_uid;
2873 -       gid_t   cr_gid;
2874 -       int     cr_ngroups;
2875 -       gid_t   cr_groups[NGROUPS];
2876 +       uint32_t cr_remote;
2877 +       uint32_t cr_usr_root;
2878 +       uint32_t cr_usr_mds;
2879 +       uid_t    cr_uid;
2880 +       uid_t    cr_mapped_uid;
2881 +       uid_t    cr_gid;
2882  };
2883  
2884  static int
2885 @@ -70,11 +72,10 @@ do_svc_downcall(gss_buffer_desc *out_han
2886                 gss_OID mech, gss_buffer_desc *context_token)
2887  {
2888         FILE *f;
2889 -       int i;
2890         char *fname = NULL;
2891         int err;
2892  
2893 -       printerr(1, "doing downcall\n");
2894 +       printerr(2, "doing downcall\n");
2895         if ((fname = mech2file(mech)) == NULL)
2896                 goto out_err;
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);
2913         err = qword_eol(f);
2914 @@ -120,7 +122,7 @@ send_response(FILE *f, gss_buffer_desc *
2915         /* XXXARG: */
2916         int g;
2917  
2918 -       printerr(1, "sending null reply\n");
2919 +       printerr(2, "sending null reply\n");
2920  
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
2926  
2927 +#if 0
2928  static void
2929  add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
2930  {
2931 @@ -183,7 +186,9 @@ add_supplementary_groups(char *secname, 
2932                 }
2933         }
2934  }
2935 +#endif
2936  
2937 +#if 0
2938  static int
2939  get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
2940  {
2941 @@ -249,7 +254,9 @@ out_free:
2942  out:
2943         return res;
2944  }
2945 +#endif
2946  
2947 +#if 0
2948  void
2949  print_hexl(int pri, unsigned char *cp, int length)
2950  {
2951 @@ -286,12 +293,149 @@ print_hexl(int pri, unsigned char *cp, i
2952                 printerr(pri,"\n");
2953         }
2954  }
2955 +#endif
2956  
2957 -void
2958 +static int
2959 +get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
2960 +       lnet_nid_t nid, uint32_t lustre_svc)
2961 +{
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];
2967 +       int             res = -1;
2968 +       gss_OID         name_type = GSS_C_NO_OID;
2969 +       struct passwd   *pw;
2970 +
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;
2973 +
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);
2978 +               return -1;
2979 +       }
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);
2985 +               return -1;
2986 +       }
2987 +       memcpy(sname, name.value, name.length);
2988 +       gss_release_buffer(&min_stat, &name);
2989 +
2990 +       if (lustre_svc == LUSTRE_GSS_SVC_MDS)
2991 +               lookup_mapping(sname, nid, &cred->cr_mapped_uid);
2992 +       else
2993 +               cred->cr_mapped_uid = -1;
2994 +
2995 +        realm = strchr(sname, '@');
2996 +       if (realm)
2997 +                *realm++ = '\0';
2998 +
2999 +        host = strchr(sname, '/');
3000 +        if (host)
3001 +                *host++ = '\0';
3002 +
3003 +       if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
3004 +               printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
3005 +               goto out_free;
3006 +       }
3007 +
3008 +       /* 1. check host part */
3009 +       if (host) {
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);
3014 +                       goto out_free;
3015 +               }
3016 +
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,
3020 +                                namebuf, nid);
3021 +                       goto out_free;
3022 +               }
3023 +       } else {
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);
3028 +                       goto out_free;
3029 +               }
3030 +       }
3031 +
3032 +       /* 2. check realm */
3033 +       if (!realm) {
3034 +               /* just deny it
3035 +                cred->cr_remote = (mds_local_realm != NULL);
3036 +               */
3037 +                printerr(0, "ERROR: %s%s%s have no realm name\n",
3038 +                        sname, host ? "/" : "", host ? "host" : "");
3039 +               goto out_free;
3040 +       }
3041 +
3042 +       if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) {
3043 +               cred->cr_remote = 1;
3044 +
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 */
3049 +               goto out_free;
3050 +       }
3051 +
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)) {
3057 +                        cred->cr_uid = 0;
3058 +                        cred->cr_usr_root = 1;
3059 +                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
3060 +                        cred->cr_uid = 0;
3061 +                        cred->cr_usr_mds = 1;
3062 +                } else {
3063 +                        if (cred->cr_mapped_uid == -1) {
3064 +                                printerr(0, "ERROR: invalid user, %s/%s@%s "
3065 +                                        "from %016llx\n", sname, host,
3066 +                                        realm, nid);
3067 +                                goto out_free;
3068 +                        }
3069 +                }
3070 +               printerr(2, "user %s from %016llx is mapped to %u\n",
3071 +                        sname, nid, cred->cr_mapped_uid);
3072 +        } else {
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);
3076 +        }
3077 +
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);
3081 +        res = 0;
3082 +out_free:
3083 +        free(sname);
3084 +        return res;
3085 +}
3086 +
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;
3091 +
3092 +/*
3093 + * return -1 only if we detect error during reading from upcall channel,
3094 + * all other cases return 0.
3095 + */
3096 +int
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;
3110 +       lnet_nid_t              nid;
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;
3121         static char             *cp;
3122  
3123 -       printerr(1, "handling null request\n");
3124 +       printerr(2, "handling null request\n");
3125  
3126         if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
3127                 printerr(0, "WARNING: handle_nullreq: "
3128                             "failed reading request\n");
3129 -               return;
3130 +               return -1;
3131         }
3132  
3133         cp = lbuf;
3134  
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);
3140 +
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);
3147  
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);
3154  
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);
3159         }
3160  
3161 -       maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
3162 +       svc_cred = gssd_select_svc_cred(lustre_svc);
3163 +       if (!svc_cred) {
3164 +               printerr(0, "no service credential for svc %u\n", lustre_svc);
3165 +               goto out_err;
3166 +       }
3167 +
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);
3171  
3172 @@ -370,7 +529,8 @@ handle_nullreq(FILE *f) {
3173                         maj_stat, min_stat, mech);
3174                 goto out_err;
3175         }
3176 -       if (get_ids(client_name, mech, &cred)) {
3177 +
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) {
3183         }
3184         gss_release_name(&ignore_min_stat, &client_name);
3185  
3186 -
3187         /* Context complete. Pass handle_seq in out_handle to use
3188          * for context lookup in the kernel. */
3189 -       handle_seq++;
3190         out_handle.length = sizeof(handle_seq);
3191         memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
3192  
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");
3198 -       return;
3199 +       return 0;
3200  
3201  out_err:
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
3206 @@ -2,30 +2,6 @@
3207  
3208  OPTDIRS =
3209  
3210 -if CONFIG_RQUOTAD
3211 -OPTDIRS += rquotad
3212 -endif
3213 -
3214 -if CONFIG_NFSV4
3215 -OPTDIRS += idmapd
3216 -endif
3217 -
3218 -if CONFIG_GSS
3219 -OPTDIRS += gssd
3220 -endif
3221 -
3222 -if CONFIG_MOUNT
3223 -OPTDIRS += mount
3224 -endif
3225 -
3226 -SUBDIRS = \
3227 -       exportfs \
3228 -       lockd \
3229 -       mountd \
3230 -       nfsd \
3231 -       nfsstat \
3232 -       showmount \
3233 -       statd \
3234 -       $(OPTDIRS)
3235 +SUBDIRS = gssd
3236  
3237  MAINTAINERCLEANFILES = Makefile.in