Whamcloud - gitweb
- make HEAD from b_post_cmd3
[fs/lustre-release.git] / lustre / utils / gss / nfs-utils-1.0.10-lustre.diff
1 diff -rup nfs-utils-1.0.10.orig/configure.in nfs-utils-1.0.10/configure.in
2 --- nfs-utils-1.0.10.orig/configure.in  2006-11-15 21:26:08.000000000 -0700
3 +++ nfs-utils-1.0.10/configure.in       2006-12-15 15:11:52.000000000 -0700
4 @@ -17,61 +17,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 @@ -81,38 +34,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 @@ -155,47 +76,17 @@ 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_SUBST(LIBSOCKET)
131  AC_SUBST(LIBCRYPT)
132  AC_SUBST(LIBBSD)
133  
134  if test "$enable_gss" = yes; then
135 -  dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
136 -  AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
137 -  AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
138 -  dnl the nfs4_set_debug function doesn't appear in all version of the library
139 -  AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
140 -              AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
141 -                        [Whether nfs4_set_debug() is present in libnfsidmap]),)
142 -
143    dnl Check for Kerberos V5
144    AC_KERBEROS_V5
145 -
146 -  dnl This is not done until here because we need to have KRBLIBS set
147 -  dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
148 -  AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
149 -  AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
150 -              AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
151 -
152  fi
153  
154  dnl *************************************************************
155 @@ -307,35 +198,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
156  
157  AC_CONFIG_FILES([
158         Makefile
159 -       linux-nfs/Makefile
160 -       support/Makefile
161 -       support/export/Makefile
162 -       support/include/nfs/Makefile
163 -       support/include/rpcsvc/Makefile
164 -       support/include/sys/fs/Makefile
165 -       support/include/sys/Makefile
166 -       support/include/Makefile
167 -       support/misc/Makefile
168 -       support/nfs/Makefile
169 -       tools/Makefile
170 -       tools/getiversion/Makefile
171 -       tools/getkversion/Makefile
172 -       tools/locktest/Makefile
173 -       tools/nlmtest/Makefile
174 -       tools/rpcdebug/Makefile
175 -       tools/rpcgen/Makefile
176         utils/Makefile
177 -       utils/exportfs/Makefile
178 -       utils/gssd/Makefile
179 -       utils/idmapd/Makefile
180 -       utils/lockd/Makefile
181 -       utils/mount/Makefile
182 -       utils/mountd/Makefile
183 -       utils/nfsd/Makefile
184 -       utils/nfsstat/Makefile
185 -       utils/nhfsstone/Makefile
186 -       utils/rquotad/Makefile
187 -       utils/showmount/Makefile
188 -       utils/statd/Makefile])
189 +       utils/gssd/Makefile])
190  AC_OUTPUT
191  
192 diff -rup nfs-utils-1.0.10.orig/Makefile.am nfs-utils-1.0.10/Makefile.am
193 --- nfs-utils-1.0.10.orig/Makefile.am   2006-11-15 21:26:08.000000000 -0700
194 +++ nfs-utils-1.0.10/Makefile.am        2006-12-15 15:11:52.000000000 -0700
195 @@ -1,6 +1,6 @@
196  ## Process this file with automake to produce Makefile.in
197  
198 -SUBDIRS = tools support utils linux-nfs
199 +SUBDIRS = utils
200  
201  MAINTAINERCLEANFILES = Makefile.in
202  
203 diff -rup nfs-utils-1.0.10.orig/utils/gssd/cacheio.c nfs-utils-1.0.10/utils/gssd/cacheio.c
204 --- nfs-utils-1.0.10.orig/utils/gssd/cacheio.c  2006-08-07 00:40:50.000000000 -0600
205 +++ nfs-utils-1.0.10/utils/gssd/cacheio.c       2006-12-15 15:12:23.000000000 -0700
206 @@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in
207                 return -1;
208         while (*bp == ' ') bp++;
209         *bpp = bp;
210 -       *dest = '\0';
211 +// why should we clear *dest???
212 +//     *dest = '\0';
213         return len;
214  }
215  
216 diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.c nfs-utils-1.0.10/utils/gssd/context.c
217 --- nfs-utils-1.0.10.orig/utils/gssd/context.c  2006-08-07 00:40:50.000000000 -0600
218 +++ nfs-utils-1.0.10/utils/gssd/context.c       2006-12-15 15:12:23.000000000 -0700
219 @@ -33,8 +33,6 @@
220  #include <syslog.h>
221  #include <string.h>
222  #include <gssapi/gssapi.h>
223 -#include <rpc/rpc.h>
224 -#include <rpc/auth_gss.h>
225  #include "gss_util.h"
226  #include "gss_oids.h"
227  #include "err_util.h"
228 diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.h nfs-utils-1.0.10/utils/gssd/context.h
229 --- nfs-utils-1.0.10.orig/utils/gssd/context.h  2006-11-15 21:26:08.000000000 -0700
230 +++ nfs-utils-1.0.10/utils/gssd/context.h       2006-12-15 15:12:23.000000000 -0700
231 @@ -31,8 +31,6 @@
232  #ifndef _CONTEXT_H_
233  #define _CONTEXT_H_
234  
235 -#include <rpc/rpc.h>
236 -
237  /* Hopefully big enough to hold any serialized context */
238  #define MAX_CTX_LEN 4096
239  
240 diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c nfs-utils-1.0.10/utils/gssd/context_lucid.c
241 --- nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c    2006-11-15 21:26:08.000000000 -0700
242 +++ nfs-utils-1.0.10/utils/gssd/context_lucid.c 2006-12-15 15:12:23.000000000 -0700
243 @@ -41,11 +41,7 @@
244  #include <syslog.h>
245  #include <string.h>
246  #include <errno.h>
247 -#include "gss_util.h"
248 -#include "gss_oids.h"
249 -#include "err_util.h"
250 -#include "context.h"
251 -
252 +#include <stdint.h>
253  #include <krb5.h>
254  #include <gssapi/gssapi.h>
255  #ifndef OM_uint64
256 @@ -53,6 +49,11 @@ typedef uint64_t OM_uint64;
257  #endif
258  #include <gssapi/gssapi_krb5.h>
259  
260 +#include "gss_util.h"
261 +#include "gss_oids.h"
262 +#include "err_util.h"
263 +#include "context.h"
264 +
265  static int
266  write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
267  {
268 @@ -354,6 +355,7 @@ static int
269  prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
270                             gss_buffer_desc *buf)
271  {
272 +       static int constant_two = 2;
273         char *p, *end;
274         uint32_t v2_flags = 0;
275         gss_krb5_lucid_key_t enc_key;
276 @@ -372,7 +374,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
277         end = buf->value + MAX_CTX_LEN;
278  
279         /* Version 2 */
280 -       if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
281 +       if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
282         if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
283  
284         if (lctx->initiate)
285 @@ -434,14 +436,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
286                         goto out_err;
287  
288                 /* Kc */
289 -               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
290 -                               &derived_key,
291 -                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
292 -                       goto out_err;
293 -               if (write_bytes(&p, end, derived_key.data,
294 -                               derived_key.length))
295 -                       goto out_err;
296 -               free(derived_key.data);
297 +               /*
298 +                * RC4 is special, it dosen't need key derivation. Actually
299 +                * the Ke is based on plain text. Here we just let all three
300 +                * key identical, kernel will handle everything. --ericm
301 +                */
302 +               if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
303 +                       if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
304 +                                       lctx->rfc1964_kd.ctx_key.length))
305 +                               goto out_err;
306 +               } else {
307 +                       if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
308 +                                       &derived_key,
309 +                                       KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
310 +                               goto out_err;
311 +                       if (write_bytes(&p, end, derived_key.data,
312 +                                       derived_key.length))
313 +                               goto out_err;
314 +                       free(derived_key.data);
315 +               }
316         } else {
317                 gss_krb5_lucid_key_t *keyptr;
318                 uint32_t sign_usage, seal_usage;
319 @@ -451,6 +464,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
320                 else
321                         keyptr = &lctx->cfx_kd.ctx_key;
322  
323 +#if 0
324                 if (lctx->initiate == 1) {
325                         sign_usage = KG_USAGE_INITIATOR_SIGN;
326                         seal_usage = KG_USAGE_INITIATOR_SEAL;
327 @@ -458,6 +472,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
328                         sign_usage = KG_USAGE_ACCEPTOR_SIGN;
329                         seal_usage = KG_USAGE_ACCEPTOR_SEAL;
330                 }
331 +#else
332 +               /* FIXME
333 +                * These are from rfc4142, but I don't understand: if we supply
334 +                * different 'usage' value for client & server, then the peers
335 +                * will have different derived keys. How could this work?
336 +                *
337 +                * Here we simply use old SIGN/SEAL values until we find the
338 +                * answer.  --ericm
339 +                * FIXME
340 +                */
341 +               sign_usage = KG_USAGE_SIGN;
342 +               seal_usage = KG_USAGE_SEAL;
343 +#endif
344  
345                 /* derive and send down: Ke, Ki, and Kc */
346  
347 diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_mit.c nfs-utils-1.0.10/utils/gssd/context_mit.c
348 --- nfs-utils-1.0.10.orig/utils/gssd/context_mit.c      2006-11-15 21:26:08.000000000 -0700
349 +++ nfs-utils-1.0.10/utils/gssd/context_mit.c   2006-12-15 15:12:23.000000000 -0700
350 @@ -39,7 +39,6 @@
351  #include <errno.h>
352  #include <gssapi/gssapi.h>
353  #include <rpc/rpc.h>
354 -#include <rpc/auth_gss.h>
355  #include "gss_util.h"
356  #include "gss_oids.h"
357  #include "err_util.h"
358 @@ -333,12 +332,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
359                  * keydata-2;                (  Ki  (Kseq for DES3) )
360                  * keydata-3;                (  Kc (derived checksum key) )
361                  */
362 -               if (kctx->initiate) {
363 -                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
364 -               }
365 -               else {
366 -                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
367 -               }
368 +               if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
369                 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
370  
371                 /* Only applicable flag for this is initiator */
372 diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c nfs-utils-1.0.10/utils/gssd/context_spkm3.c
373 --- nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c    2006-11-15 21:26:08.000000000 -0700
374 +++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2006-12-15 15:12:23.000000000 -0700
375 @@ -33,8 +33,6 @@
376  #include <syslog.h>
377  #include <string.h>
378  #include <gssapi/gssapi.h>
379 -#include <rpc/rpc.h>
380 -#include <rpc/auth_gss.h>
381  #include "gss_util.h"
382  #include "gss_oids.h"
383  #include "err_util.h"
384 diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.c nfs-utils-1.0.10/utils/gssd/err_util.c
385 --- nfs-utils-1.0.10.orig/utils/gssd/err_util.c 2006-08-07 00:40:50.000000000 -0600
386 +++ nfs-utils-1.0.10/utils/gssd/err_util.c      2006-12-15 15:12:23.000000000 -0700
387 @@ -32,6 +32,8 @@
388  #include <stdarg.h>
389  #include <syslog.h>
390  #include <string.h>
391 +#include <fcntl.h>
392 +#include <ctype.h>
393  #include "err_util.h"
394  
395  static int verbosity = 0;
396 @@ -91,3 +93,40 @@ printit:
397         /* reset the buffer */
398         memset(message_buf, 0, sizeof(message_buf));
399  }
400 +
401 +void print_hexl(int pri, unsigned char *cp, int length)
402 +{
403 +       int i, j, jm;
404 +       unsigned char c;
405 +
406 +       printerr(pri, "length %d\n",length);
407 +       printerr(pri, "\n");
408 +
409 +       for (i = 0; i < length; i += 0x10) {
410 +               printerr(pri, "  %04x: ", (u_int)i);
411 +               jm = length - i;
412 +               jm = jm > 16 ? 16 : jm;
413 +
414 +               for (j = 0; j < jm; j++) {
415 +                       if ((j % 2) == 1)
416 +                               printerr(pri,"%02x ", (u_int)cp[i+j]);
417 +                       else
418 +                               printerr(pri,"%02x", (u_int)cp[i+j]);
419 +               }
420 +               for (; j < 16; j++) {
421 +                       if ((j % 2) == 1)
422 +                               printerr(pri,"   ");
423 +                       else
424 +                               printerr(pri,"  ");
425 +               }
426 +               printerr(pri," ");
427 +
428 +               for (j = 0; j < jm; j++) {
429 +                       c = cp[i+j];
430 +                       c = isprint(c) ? c : '.';
431 +                       printerr(pri,"%c", c);
432 +               }
433 +               printerr(pri,"\n");
434 +       }
435 +}
436 +
437 diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.h nfs-utils-1.0.10/utils/gssd/err_util.h
438 --- nfs-utils-1.0.10.orig/utils/gssd/err_util.h 2006-08-07 00:40:50.000000000 -0600
439 +++ nfs-utils-1.0.10/utils/gssd/err_util.h      2006-12-15 15:12:23.000000000 -0700
440 @@ -33,5 +33,6 @@
441  
442  void initerr(char *progname, int verbosity, int fg);
443  void printerr(int priority, char *format, ...);
444 +void print_hexl(int pri, unsigned char *cp, int length);
445  
446  #endif /* _ERR_UTIL_H_ */
447 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c
448 --- nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c        2006-08-07 00:40:50.000000000 -0600
449 +++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c     2006-12-15 15:12:23.000000000 -0700
450 @@ -47,6 +47,7 @@
451  #include "gssd.h"
452  #include "write_bytes.h"
453  
454 +#if 0
455  char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
456  
457  static void
458 @@ -102,3 +103,4 @@ main(int argc, char *argv[])
459         }
460         exit(0);
461  }
462 +#endif
463 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.c nfs-utils-1.0.10/utils/gssd/gssd.c
464 --- nfs-utils-1.0.10.orig/utils/gssd/gssd.c     2006-11-15 21:26:08.000000000 -0700
465 +++ nfs-utils-1.0.10/utils/gssd/gssd.c  2006-12-15 15:12:23.000000000 -0700
466 @@ -38,9 +38,12 @@
467  
468  #include "config.h"
469  
470 +#include <sys/types.h>
471  #include <sys/param.h>
472  #include <sys/socket.h>
473 -#include <rpc/rpc.h>
474 +#include <sys/wait.h>
475 +#include <sys/ipc.h>
476 +#include <sys/sem.h>
477  
478  #include <unistd.h>
479  #include <err.h>
480 @@ -48,23 +51,107 @@
481  #include <stdlib.h>
482  #include <string.h>
483  #include <signal.h>
484 +#include <errno.h>
485  #include "gssd.h"
486  #include "err_util.h"
487  #include "gss_util.h"
488  #include "krb5_util.h"
489 +#include "lsupport.h"
490  
491  char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
492  char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
493  char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
494  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
495  int  use_memcache = 0;
496 +int  lgssd_mutex_downcall = -1;
497  
498 -void
499 -sig_die(int signal)
500 +static int lgssd_create_mutex(int *semid)
501 +{
502 +       int             id;
503 +       int             arg;
504 +
505 +       id = semget(IPC_PRIVATE, 1, IPC_CREAT);
506 +       if (id == -1) {
507 +               printerr(0, "semget: %s\n", strerror(errno));
508 +               return -1;
509 +       }
510 +
511 +       arg = 1;
512 +       if (semctl(id, 0, SETVAL, arg) != 0) {
513 +               printerr(0, "semctl: %s\n", strerror(errno));
514 +               semctl(id, 1, IPC_RMID, arg);
515 +               return -1;
516 +       }
517 +
518 +       *semid = id;
519 +       return 0;
520 +}
521 +
522 +void lgssd_init_mutexs(void)
523 +{
524 +       if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
525 +               printerr(0, "can't create downcall mutex\n");
526 +               exit(1);
527 +       }
528 +}
529 +
530 +void lgssd_fini_mutexs(void)
531 +{
532 +       int     arg = 0;
533 +
534 +       if (lgssd_mutex_downcall != -1)
535 +               semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
536 +}
537 +
538 +void lgssd_mutex_get(int semid)
539 +{
540 +       struct sembuf   op[1] = { {0, -1, SEM_UNDO} };
541 +       int             rc;
542 +
543 +       rc = semop(semid, op, 1);
544 +       if (rc != 0) {
545 +               printerr(0, "exit on mutex_get err %d: %s\n",
546 +                        rc, strerror(errno));
547 +               exit(1);
548 +       }
549 +}
550 +
551 +void lgssd_mutex_put(int semid)
552  {
553 +       struct sembuf   op[1] = { {0, 1, 0} };
554 +       int             rc;
555 +
556 +       rc = semop(semid, op, 1);
557 +       if (rc != 0) {
558 +               printerr(0, "ignore mutex_put err %d: %s\n",
559 +                        rc, strerror(errno));
560 +       }
561 +}
562 +
563 +static void lgssd_cleanup(void)
564 +{
565 +       pid_t   child_pid;
566 +
567 +       /* make sure all children finished */
568 +       while (1) {
569 +               child_pid = waitpid(-1, NULL, 0);
570 +               if (child_pid < 0)
571 +                       break;
572 +
573 +               printerr(3, "cleanup: child %d terminated\n", child_pid);
574 +       }
575 +
576 +       lgssd_fini_mutexs();
577 +
578         /* destroy krb5 machine creds */
579         gssd_destroy_krb5_machine_creds();
580 +}
581 +
582 +void
583 +sig_die(int signal)
584 +{
585         printerr(1, "exiting on signal %d\n", signal);
586 +       lgssd_cleanup();
587         exit(1);
588  }
589  
590 @@ -79,7 +166,7 @@ sig_hup(int signal)
591  static void
592  usage(char *progname)
593  {
594 -       fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
595 +       fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
596                 progname);
597         exit(1);
598  }
599 @@ -89,7 +176,6 @@ main(int argc, char *argv[])
600  {
601         int fg = 0;
602         int verbosity = 0;
603 -       int rpc_verbosity = 0;
604         int opt;
605         extern char *optarg;
606         char *progname;
607 @@ -99,18 +185,12 @@ main(int argc, char *argv[])
608                         case 'f':
609                                 fg = 1;
610                                 break;
611 -                       case 'm':
612 -                               /* Accept but ignore this. Now the default. */
613 -                               break;
614                         case 'M':
615                                 use_memcache = 1;
616                                 break;
617                         case 'v':
618                                 verbosity++;
619                                 break;
620 -                       case 'r':
621 -                               rpc_verbosity++;
622 -                               break;
623                         case 'p':
624                                 strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
625                                 if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
626 @@ -131,10 +211,6 @@ main(int argc, char *argv[])
627                                 break;
628                 }
629         }
630 -       snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
631 -                pipefs_dir, GSSD_SERVICE_NAME);
632 -       if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
633 -               errx(1, "pipefs_nfsdir path name too long");
634  
635         if ((progname = strrchr(argv[0], '/')))
636                 progname++;
637 @@ -142,30 +218,42 @@ main(int argc, char *argv[])
638                 progname = argv[0];
639  
640         initerr(progname, verbosity, fg);
641 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
642 -       authgss_set_debug_level(rpc_verbosity);
643 -#else
644 -        if (rpc_verbosity > 0)
645 -               printerr(0, "Warning: rpcsec_gss library does not "
646 -                           "support setting debug level\n");
647 -#endif
648  
649         if (gssd_check_mechs() != 0)
650                 errx(1, "Problem with gssapi library");
651  
652 +       if (gssd_get_local_realm())
653 +               errx(1, "get local realm");
654 +
655         if (!fg && daemon(0, 0) < 0)
656                 errx(1, "fork");
657  
658 +       /* This should be checked _after_ daemon(), because we need to own
659 +        * the undo-able semaphore by this process
660 +        */
661 +       gssd_init_unique(GSSD_CLI);
662 +
663 +       /* Process keytab file and get machine credentials. This will modify
664 +        * disk status so do it after we are sure we are the only instance
665 +        */
666 +       if (gssd_refresh_krb5_machine_creds())
667 +               return -1;
668 +
669         signal(SIGINT, sig_die);
670         signal(SIGTERM, sig_die);
671         signal(SIGHUP, sig_hup);
672  
673 -       /* Process keytab file and get machine credentials */
674 -       gssd_refresh_krb5_machine_creds();
675 +#if 0
676         /* Determine Kerberos information from the kernel */
677         gssd_obtain_kernel_krb5_info();
678 +#endif
679 +
680 +       lgssd_init_mutexs();
681 +
682 +       printerr(0, "lgssd initialized and ready to serve\n");
683 +       lgssd_run();
684  
685 -       gssd_run();
686 -       printerr(0, "gssd_run returned!\n");
687 -       abort();
688 +       lgssd_cleanup();
689 +       printerr(0, "lgssd exiting\n");
690 +       return 0;
691  }
692 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.h nfs-utils-1.0.10/utils/gssd/gssd.h
693 --- nfs-utils-1.0.10.orig/utils/gssd/gssd.h     2006-11-15 21:26:08.000000000 -0700
694 +++ nfs-utils-1.0.10/utils/gssd/gssd.h  2006-12-15 15:12:23.000000000 -0700
695 @@ -48,8 +48,13 @@
696  #define GSSD_DEFAULT_CRED_PREFIX               "krb5cc_"
697  #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX       "machine"
698  #define GSSD_DEFAULT_KEYTAB_FILE               "/etc/krb5.keytab"
699 -#define GSSD_SERVICE_NAME                      "nfs"
700 -#define GSSD_SERVICE_NAME_LEN                  3
701 +#define GSSD_SERVICE_MDS                       "lustre_mds"
702 +#define GSSD_SERVICE_OSS                       "lustre_oss"
703 +#define GSSD_SERVICE_MDS_NAMELEN               10
704 +#define GSSD_SERVICE_OSS_NAMELEN               10
705 +
706 +#define LUSTRE_ROOT_NAME                       "lustre_root"
707 +#define LUSTRE_ROOT_NAMELEN                    11
708  
709  /*
710   * The gss mechanisms that we can handle
711 @@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
712  
713  
714  extern char                    pipefs_dir[PATH_MAX];
715 -extern char                    pipefs_nfsdir[PATH_MAX];
716  extern char                    keytabfile[PATH_MAX];
717  extern char                    ccachedir[PATH_MAX];
718 +extern char                    gethostname_ex[PATH_MAX];
719  extern int                     use_memcache;
720  
721  TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
722 @@ -71,10 +76,6 @@ struct clnt_info {
723         char                    *dirname;
724         int                     dir_fd;
725         char                    *servicename;
726 -       char                    *servername;
727 -       int                     prog;
728 -       int                     vers;
729 -       char                    *protocol;
730         int                     krb5_fd;
731         int                     krb5_poll_index;
732         int                     spkm3_fd;
733 @@ -85,8 +86,14 @@ void init_client_list(void);
734  int update_client_list(void);
735  void handle_krb5_upcall(struct clnt_info *clp);
736  void handle_spkm3_upcall(struct clnt_info *clp);
737 -int gssd_acquire_cred(char *server_name);
738 -void gssd_run(void);
739 +void lgssd_run(void);
740 +
741 +
742 +extern int lgssd_mutex_downcall;
743  
744 +void lgssd_init_mutexs(void);
745 +void lgssd_fini_mutexs(void);
746 +void lgssd_mutex_get(int semid);
747 +void lgssd_mutex_put(int semid);
748  
749  #endif /* _RPC_GSSD_H_ */
750 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c
751 --- nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c   2006-11-15 21:26:08.000000000 -0700
752 +++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c        2006-12-15 15:12:23.000000000 -0700
753 @@ -94,11 +94,13 @@ scan_poll_results(int ret)
754  };
755  
756  void
757 -gssd_run()
758 +lgssd_run()
759  {
760         int                     ret;
761         struct sigaction        dn_act;
762         int                     fd;
763 +       time_t                  child_check = 0;
764 +       pid_t                   child_pid;
765  
766         /* Taken from linux/Documentation/dnotify.txt: */
767         dn_act.sa_sigaction = dir_notify_handler;
768 @@ -106,10 +108,10 @@ gssd_run()
769         dn_act.sa_flags = SA_SIGINFO;
770         sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
771  
772 -       if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
773 +       if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
774                 printerr(0, "ERROR: failed to open %s: %s\n",
775 -                        pipefs_nfsdir, strerror(errno));
776 -               exit(1);
777 +                        pipefs_dir, strerror(errno));
778 +               return;
779         }
780         fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
781         fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
782 @@ -119,12 +121,30 @@ gssd_run()
783         while (1) {
784                 while (dir_changed) {
785                         dir_changed = 0;
786 +                       printerr(2, "pipefs root dir changed\n");
787                         if (update_client_list()) {
788                                 printerr(0, "ERROR: couldn't update "
789                                          "client list\n");
790 -                               exit(1);
791 +                               goto out;
792                         }
793                 }
794 +
795 +               /* every 5s cleanup possible zombies of child processes */
796 +               if (time(NULL) - child_check >= 5) {
797 +                       printerr(3, "check zombie children...\n");
798 +
799 +                       while (1) {
800 +                               child_pid = waitpid(-1, NULL, WNOHANG);
801 +                               if (child_pid <= 0)
802 +                                       break;
803 +
804 +                               printerr(2, "terminate zombie child: %d\n",
805 +                                        child_pid);
806 +                       }
807 +
808 +                       child_check = time(NULL);
809 +               }
810 +
811                 /* race condition here: dir_changed could be set before we
812                  * enter the poll, and we'd never notice if it weren't for the
813                  * timeout. */
814 @@ -139,6 +159,7 @@ gssd_run()
815                         scan_poll_results(ret);
816                 }
817         }
818 +out:
819         close(fd);
820         return;
821  }
822 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c nfs-utils-1.0.10/utils/gssd/gssd_proc.c
823 --- nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c        2006-11-15 21:26:08.000000000 -0700
824 +++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c     2006-12-15 15:12:23.000000000 -0700
825 @@ -43,7 +43,6 @@
826  #endif
827  #include "config.h"
828  #include <sys/param.h>
829 -#include <rpc/rpc.h>
830  #include <sys/stat.h>
831  #include <sys/socket.h>
832  #include <arpa/inet.h>
833 @@ -69,6 +68,7 @@
834  #include "gss_oids.h"
835  #include "krb5_util.h"
836  #include "context.h"
837 +#include "lsupport.h"
838  
839  /*
840   * pollarray:
841 @@ -99,86 +99,10 @@ struct pollfd * pollarray;
842  
843  int pollsize;  /* the size of pollaray (in pollfd's) */
844  
845 -/* XXX buffer problems: */
846 -static int
847 -read_service_info(char *info_file_name, char **servicename, char **servername,
848 -                 int *prog, int *vers, char **protocol) {
849 -#define INFOBUFLEN 256
850 -       char            buf[INFOBUFLEN];
851 -       static char     dummy[128];
852 -       int             nbytes;
853 -       static char     service[128];
854 -       static char     address[128];
855 -       char            program[16];
856 -       char            version[16];
857 -       char            protoname[16];
858 -       in_addr_t       inaddr;
859 -       int             fd = -1;
860 -       struct hostent  *ent = NULL;
861 -       int             numfields;
862 -
863 -       *servicename = *servername = *protocol = NULL;
864 -
865 -       if ((fd = open(info_file_name, O_RDONLY)) == -1) {
866 -               printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
867 -                        strerror(errno));
868 -               goto fail;
869 -       }
870 -       if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
871 -               goto fail;
872 -       close(fd);
873 -
874 -       numfields = sscanf(buf,"RPC server: %127s\n"
875 -                  "service: %127s %15s version %15s\n"
876 -                  "address: %127s\n"
877 -                  "protocol: %15s\n",
878 -                  dummy,
879 -                  service, program, version,
880 -                  address,
881 -                  protoname);
882 -
883 -       if (numfields == 5) {
884 -               strcpy(protoname, "tcp");
885 -       } else if (numfields != 6) {
886 -               goto fail;
887 -       }
888 -
889 -       /* check service, program, and version */
890 -       if(memcmp(service, "nfs", 3)) return -1;
891 -       *prog = atoi(program + 1); /* skip open paren */
892 -       *vers = atoi(version);
893 -       if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
894 -               goto fail;
895 -
896 -       /* create service name */
897 -       inaddr = inet_addr(address);
898 -       if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
899 -               printerr(0, "ERROR: can't resolve server %s name\n", address);
900 -               goto fail;
901 -       }
902 -       if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
903 -               goto fail;
904 -       memcpy(*servername, ent->h_name, strlen(ent->h_name));
905 -       snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
906 -       if (!(*servicename = calloc(strlen(buf) + 1, 1)))
907 -               goto fail;
908 -       memcpy(*servicename, buf, strlen(buf));
909 -
910 -       if (!(*protocol = strdup(protoname)))
911 -               goto fail;
912 -       return 0;
913 -fail:
914 -       printerr(0, "ERROR: failed to read service info\n");
915 -       if (fd != -1) close(fd);
916 -       if (*servername) free(*servername);
917 -       if (*servicename) free(*servicename);
918 -       if (*protocol) free(*protocol);
919 -       return -1;
920 -}
921 -
922  static void
923  destroy_client(struct clnt_info *clp)
924  {
925 +       printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
926         if (clp->krb5_poll_index != -1)
927                 memset(&pollarray[clp->krb5_poll_index], 0,
928                                         sizeof(struct pollfd));
929 @@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
930         if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
931         if (clp->dirname) free(clp->dirname);
932         if (clp->servicename) free(clp->servicename);
933 -       if (clp->servername) free(clp->servername);
934 -       if (clp->protocol) free(clp->protocol);
935         free(clp);
936  }
937  
938 @@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info 
939  {
940         char    kname[32];
941         char    sname[32];
942 -       char    info_file_name[32];
943  
944         if (clp->krb5_fd == -1) {
945                 snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
946 @@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info 
947         }
948         if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
949                 return -1;
950 -       snprintf(info_file_name, sizeof(info_file_name), "%s/info",
951 -                       clp->dirname);
952 -       if ((clp->servicename == NULL) &&
953 -            read_service_info(info_file_name, &clp->servicename,
954 -                               &clp->servername, &clp->prog, &clp->vers,
955 -                               &clp->protocol))
956 -               return -1;
957         return 0;
958  }
959  
960 @@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
961                 }
962                 pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
963                 pollarray[clp->krb5_poll_index].events |= POLLIN;
964 +               printerr(2, "monitoring krb5 channel under %s\n",
965 +                        clp->dirname);
966         }
967  
968         if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
969 @@ -386,67 +302,106 @@ find_client(char *dirname)
970  int
971  update_client_list(void)
972  {
973 -       struct dirent **namelist;
974 +       char lustre_dir[PATH_MAX];
975 +       struct dirent lustre_dirent = { .d_name = "lustre" };
976 +       struct dirent *namelist[1];
977 +       struct stat statbuf;
978         int i, j;
979  
980 -       if (chdir(pipefs_nfsdir) < 0) {
981 +       if (chdir(pipefs_dir) < 0) {
982                 printerr(0, "ERROR: can't chdir to %s: %s\n",
983 -                        pipefs_nfsdir, strerror(errno));
984 +                        pipefs_dir, strerror(errno));
985                 return -1;
986         }
987  
988 -       j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
989 -       if (j < 0) {
990 -               printerr(0, "ERROR: can't scandir %s: %s\n",
991 -                        pipefs_nfsdir, strerror(errno));
992 -               return -1;
993 +       snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
994 +       if (stat(lustre_dir, &statbuf) == 0) {
995 +               namelist[0] = &lustre_dirent;
996 +               j = 1;
997 +               printerr(2, "re-processing lustre directory\n");
998 +       } else {
999 +               namelist[0] = NULL;
1000 +               j = 0;
1001 +               printerr(2, "lustre directory not exist\n");
1002         }
1003 +
1004         update_old_clients(namelist, j);
1005         for (i=0; i < j; i++) {
1006 -               if (i < FD_ALLOC_BLOCK
1007 -                               && !strncmp(namelist[i]->d_name, "clnt", 4)
1008 -                               && !find_client(namelist[i]->d_name))
1009 +               if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
1010                         process_clnt_dir(namelist[i]->d_name);
1011 -               free(namelist[i]);
1012         }
1013  
1014 -       free(namelist);
1015 +       chdir("/");
1016         return 0;
1017  }
1018  
1019 +/* Context creation response. */
1020 +struct lustre_gss_init_res {
1021 +        gss_buffer_desc gr_ctx;         /* context handle */
1022 +        u_int           gr_major;       /* major status */
1023 +        u_int           gr_minor;       /* minor status */
1024 +        u_int           gr_win;         /* sequence window */
1025 +        gss_buffer_desc gr_token;       /* token */
1026 +};
1027 +
1028 +struct lustre_gss_data {
1029 +        int             lgd_established;
1030 +        int             lgd_lustre_svc; /* mds/oss */
1031 +        int             lgd_uid;        /* uid */
1032 +        char           *lgd_uuid;       /* client device uuid */
1033 +        gss_name_t      lgd_name;       /* service name */
1034 +
1035 +        gss_OID         lgd_mech;       /* mech OID */
1036 +        u_int           lgd_req_flags;  /* request flags */
1037 +        gss_cred_id_t   lgd_cred;       /* credential */
1038 +        gss_ctx_id_t    lgd_ctx;        /* session context */
1039 +        gss_buffer_desc lgd_rmt_ctx;    /* remote handle of context */
1040 +        uint32_t        lgd_seq_win;    /* sequence window */
1041 +
1042 +        int             lgd_rpc_err;
1043 +        int             lgd_gss_err;
1044 +};
1045 +
1046  static int
1047 -do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
1048 -           gss_buffer_desc *context_token)
1049 +do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
1050 +            struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
1051  {
1052         char    *buf = NULL, *p = NULL, *end = NULL;
1053         unsigned int timeout = 0; /* XXX decide on a reasonable value */
1054         unsigned int buf_size = 0;
1055  
1056 -       printerr(1, "doing downcall\n");
1057 -       buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
1058 -               sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
1059 +       printerr(2, "doing downcall\n");
1060 +       buf_size = sizeof(updata->seq) + sizeof(timeout) +
1061 +               sizeof(lgd->lgd_seq_win) +
1062 +               sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
1063                 sizeof(context_token->length) + context_token->length;
1064         p = buf = malloc(buf_size);
1065         end = buf + buf_size;
1066  
1067 -       if (WRITE_BYTES(&p, end, uid)) goto out_err;
1068 +       if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
1069         /* Not setting any timeout for now: */
1070         if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1071 -       if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
1072 -       if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
1073 +       if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
1074 +       if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
1075         if (write_buffer(&p, end, context_token)) goto out_err;
1076  
1077 -       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1078 +       lgssd_mutex_get(lgssd_mutex_downcall);
1079 +       if (write(k5_fd, buf, p - buf) < p - buf) {
1080 +               lgssd_mutex_put(lgssd_mutex_downcall);
1081 +               goto out_err;
1082 +       }
1083 +       lgssd_mutex_put(lgssd_mutex_downcall);
1084 +
1085         if (buf) free(buf);
1086         return 0;
1087  out_err:
1088         if (buf) free(buf);
1089 -       printerr(0, "Failed to write downcall!\n");
1090 +       printerr(0, "ERROR: Failed to write downcall!\n");
1091         return -1;
1092  }
1093  
1094  static int
1095 -do_error_downcall(int k5_fd, uid_t uid, int err)
1096 +do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
1097  {
1098         char    buf[1024];
1099         char    *p = buf, *end = buf + 1024;
1100 @@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, 
1101  
1102         printerr(1, "doing error downcall\n");
1103  
1104 -       if (WRITE_BYTES(&p, end, uid)) goto out_err;
1105 +       if (WRITE_BYTES(&p, end, seq)) goto out_err;
1106         if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1107         /* use seq_win = 0 to indicate an error: */
1108         if (WRITE_BYTES(&p, end, zero)) goto out_err;
1109 -       if (WRITE_BYTES(&p, end, err)) goto out_err;
1110 +       if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
1111 +       if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
1112  
1113 -       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1114 +       lgssd_mutex_get(lgssd_mutex_downcall);
1115 +       if (write(k5_fd, buf, p - buf) < p - buf) {
1116 +               lgssd_mutex_put(lgssd_mutex_downcall);
1117 +               goto out_err;
1118 +       }
1119 +       lgssd_mutex_put(lgssd_mutex_downcall);
1120         return 0;
1121  out_err:
1122         printerr(0, "Failed to write error downcall!\n");
1123         return -1;
1124  }
1125  
1126 +#if 0
1127  /*
1128   * Create an RPC connection and establish an authenticated
1129   * gss context with a server.
1130 @@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
1131  
1132         goto out;
1133  }
1134 +#endif
1135 +
1136 +static
1137 +int do_negotiation(struct lustre_gss_data *lgd,
1138 +                  gss_buffer_desc *gss_token,
1139 +                  struct lustre_gss_init_res *gr,
1140 +                  int timeout)
1141 +{
1142 +       char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
1143 +       struct lgssd_ioctl_param param;
1144 +       struct passwd *pw;
1145 +       int fd, ret;
1146 +       char outbuf[8192];
1147 +       unsigned int *p;
1148 +       int res;
1149 +
1150 +       pw = getpwuid(lgd->lgd_uid);
1151 +       if (!pw) {
1152 +               printerr(0, "no uid %u in local user database\n",
1153 +                        lgd->lgd_uid);
1154 +               return -1;
1155 +       }
1156 +
1157 +       param.version = GSSD_INTERFACE_VERSION;
1158 +       param.uuid = lgd->lgd_uuid;
1159 +       param.lustre_svc = lgd->lgd_lustre_svc;
1160 +       param.uid = lgd->lgd_uid;
1161 +       param.gid = pw->pw_gid;
1162 +       param.send_token_size = gss_token->length;
1163 +       param.send_token = (char *) gss_token->value;
1164 +       param.reply_buf_size = sizeof(outbuf);
1165 +       param.reply_buf = outbuf;
1166 +
1167 +       fd = open(file, O_RDWR);
1168 +       if (fd < 0) {
1169 +               printerr(0, "can't open file %s\n", file);
1170 +               return -1;
1171 +       }
1172 +
1173 +       ret = write(fd, &param, sizeof(param));
1174 +
1175 +       if (ret != sizeof(param)) {
1176 +               printerr(0, "lustre ioctl err: %d\n", strerror(errno));
1177 +               close(fd);
1178 +               return -1;
1179 +       }
1180 +       if (param.status) {
1181 +               close(fd);
1182 +               printerr(0, "status: %d (%s)\n",
1183 +                        param.status, strerror((int)param.status));
1184 +               if (param.status == -ETIMEDOUT) {
1185 +                       /* kernel return -ETIMEDOUT means the rpc timedout,
1186 +                        * we should notify the caller to reinitiate the
1187 +                        * gss negotiation, by return -ERESTART
1188 +                        */
1189 +                       lgd->lgd_rpc_err = -ERESTART;
1190 +                       lgd->lgd_gss_err = 0;
1191 +               } else {
1192 +                       lgd->lgd_rpc_err = param.status;
1193 +                       lgd->lgd_gss_err = 0;
1194 +               }
1195 +               return -1;
1196 +       }
1197 +       p = (unsigned int *)outbuf;
1198 +       res = *p++;
1199 +       gr->gr_major = *p++;
1200 +       gr->gr_minor = *p++;
1201 +       gr->gr_win = *p++;
1202 +
1203 +       gr->gr_ctx.length = *p++;
1204 +       gr->gr_ctx.value = malloc(gr->gr_ctx.length);
1205 +       memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
1206 +       p += (((gr->gr_ctx.length + 3) & ~3) / 4);
1207 +
1208 +       gr->gr_token.length = *p++;
1209 +       gr->gr_token.value = malloc(gr->gr_token.length);
1210 +       memcpy(gr->gr_token.value, p, gr->gr_token.length);
1211 +       p += (((gr->gr_token.length + 3) & ~3) / 4);
1212 +
1213 +       printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
1214 +                gr->gr_ctx.length, gr->gr_token.length);
1215 +       close(fd);
1216 +       return 0;
1217 +}
1218 +
1219 +static
1220 +int gssd_refresh_lgd(struct lustre_gss_data *lgd)
1221 +{
1222 +       struct lustre_gss_init_res gr;
1223 +       gss_buffer_desc         *recv_tokenp, send_token;
1224 +       OM_uint32                maj_stat, min_stat, call_stat, ret_flags;
1225 +
1226 +       /* GSS context establishment loop. */
1227 +       memset(&gr, 0, sizeof(gr));
1228 +       recv_tokenp = GSS_C_NO_BUFFER;
1229 +
1230 +       for (;;) {
1231 +               /* print the token we just received */
1232 +               if (recv_tokenp != GSS_C_NO_BUFFER) {
1233 +                       printerr(3, "The received token length %d\n",
1234 +                                recv_tokenp->length);
1235 +                       print_hexl(3, recv_tokenp->value, recv_tokenp->length);
1236 +               }
1237 +
1238 +               maj_stat = gss_init_sec_context(&min_stat,
1239 +                                               lgd->lgd_cred,
1240 +                                               &lgd->lgd_ctx,
1241 +                                               lgd->lgd_name,
1242 +                                               lgd->lgd_mech,
1243 +                                               lgd->lgd_req_flags,
1244 +                                               0,              /* time req */
1245 +                                               NULL,           /* channel */
1246 +                                               recv_tokenp,
1247 +                                               NULL,           /* used mech */
1248 +                                               &send_token,
1249 +                                               &ret_flags,
1250 +                                               NULL);          /* time rec */
1251 +
1252 +               if (recv_tokenp != GSS_C_NO_BUFFER) {
1253 +                       gss_release_buffer(&min_stat, &gr.gr_token);
1254 +                       recv_tokenp = GSS_C_NO_BUFFER;
1255 +               }
1256 +               if (maj_stat != GSS_S_COMPLETE &&
1257 +                   maj_stat != GSS_S_CONTINUE_NEEDED) {
1258 +                       pgsserr("gss_init_sec_context", maj_stat, min_stat,
1259 +                               lgd->lgd_mech);
1260 +                       break;
1261 +               }
1262 +               if (send_token.length != 0) {
1263 +                       memset(&gr, 0, sizeof(gr));
1264 +
1265 +                       /* print the token we are about to send */
1266 +                       printerr(3, "token being sent length %d\n",
1267 +                                send_token.length);
1268 +                       print_hexl(3, send_token.value, send_token.length);
1269 +
1270 +                       call_stat = do_negotiation(lgd, &send_token, &gr, 0);
1271 +                       gss_release_buffer(&min_stat, &send_token);
1272 +
1273 +                       if (call_stat != 0 ||
1274 +                           (gr.gr_major != GSS_S_COMPLETE &&
1275 +                            gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
1276 +                               printerr(0, "call stat %d, major stat 0x%x\n",
1277 +                                        (int)call_stat, gr.gr_major);
1278 +                               return -1;
1279 +                       }
1280 +
1281 +                       if (gr.gr_ctx.length != 0) {
1282 +                               if (lgd->lgd_rmt_ctx.value)
1283 +                                       gss_release_buffer(&min_stat,
1284 +                                                          &lgd->lgd_rmt_ctx);
1285 +                               lgd->lgd_rmt_ctx = gr.gr_ctx;
1286 +                       }
1287 +                       if (gr.gr_token.length != 0) {
1288 +                               if (maj_stat != GSS_S_CONTINUE_NEEDED)
1289 +                                       break;
1290 +                               recv_tokenp = &gr.gr_token;
1291 +                       }
1292 +               }
1293 +
1294 +               /* GSS_S_COMPLETE => check gss header verifier,
1295 +                * usually checked in gss_validate
1296 +                */
1297 +               if (maj_stat == GSS_S_COMPLETE) {
1298 +                       lgd->lgd_established = 1;
1299 +                       lgd->lgd_seq_win = gr.gr_win;
1300 +                       break;
1301 +               }
1302 +       }
1303 +       /* End context negotiation loop. */
1304 +       if (!lgd->lgd_established) {
1305 +               if (gr.gr_token.length != 0)
1306 +                       gss_release_buffer(&min_stat, &gr.gr_token);
1307 +
1308 +               printerr(0, "context negotiation failed\n");
1309 +               return -1;
1310 +       }
1311 +
1312 +       printerr(2, "successfully refreshed lgd\n");
1313 +       return 0;
1314 +}
1315 +
1316 +static
1317 +int gssd_create_lgd(struct clnt_info *clp,
1318 +                   struct lustre_gss_data *lgd,
1319 +                   struct lgssd_upcall_data *updata,
1320 +                   int authtype)
1321 +{
1322 +       gss_buffer_desc         sname;
1323 +       OM_uint32               maj_stat, min_stat;
1324 +       int                     retval = -1;
1325 +
1326 +       lgd->lgd_established = 0;
1327 +       lgd->lgd_lustre_svc = updata->svc;
1328 +       lgd->lgd_uid = updata->uid;
1329 +       lgd->lgd_uuid = updata->obd;
1330 +
1331 +       switch (authtype) {
1332 +       case AUTHTYPE_KRB5:
1333 +               lgd->lgd_mech = (gss_OID) &krb5oid;
1334 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1335 +               break;
1336 +       case AUTHTYPE_SPKM3:
1337 +               lgd->lgd_mech = (gss_OID) &spkm3oid;
1338 +               /* XXX sec.req_flags = GSS_C_ANON_FLAG;
1339 +                * Need a way to switch....
1340 +                */
1341 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1342 +               break;
1343 +       default:
1344 +               printerr(0, "Invalid authentication type (%d)\n", authtype);
1345 +               return -1;
1346 +       }
1347 +
1348 +       lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
1349 +       lgd->lgd_ctx = GSS_C_NO_CONTEXT;
1350 +       lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
1351 +       lgd->lgd_seq_win = 0;
1352 +
1353 +       sname.value = clp->servicename;
1354 +       sname.length = strlen(clp->servicename);
1355 +
1356 +       maj_stat = gss_import_name(&min_stat, &sname,
1357 +                                  (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
1358 +                                  &lgd->lgd_name);
1359 +       if (maj_stat != GSS_S_COMPLETE) {
1360 +               pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
1361 +               goto out_fail;
1362 +       }
1363  
1364 +       retval = gssd_refresh_lgd(lgd);
1365 +
1366 +       if (lgd->lgd_name != GSS_C_NO_NAME)
1367 +               gss_release_name(&min_stat, &lgd->lgd_name);
1368 +
1369 +       if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
1370 +               gss_release_cred(&min_stat, &lgd->lgd_cred);
1371 +
1372 +  out_fail:
1373 +       return retval;
1374 +}
1375 +
1376 +static
1377 +void gssd_free_lgd(struct lustre_gss_data *lgd)
1378 +{
1379 +       gss_buffer_t            token = GSS_C_NO_BUFFER;
1380 +       OM_uint32               maj_stat, min_stat;
1381 +
1382 +       if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
1383 +               return;
1384 +
1385 +       maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
1386 +}
1387 +
1388 +static
1389 +int construct_service_name(struct clnt_info *clp,
1390 +                           struct lgssd_upcall_data *ud)
1391 +{
1392 +        const int buflen = 256;
1393 +        char name[buflen];
1394 +
1395 +        if (clp->servicename) {
1396 +                free(clp->servicename);
1397 +                clp->servicename = NULL;
1398 +        }
1399 +
1400 +        if (lnet_nid2hostname(ud->nid, name, buflen))
1401 +                return -1;
1402 +
1403 +        clp->servicename = malloc(32 + strlen(name));
1404 +        if (!clp->servicename) {
1405 +                printerr(0, "can't alloc memory\n");
1406 +                return -1;
1407 +        }
1408 +        sprintf(clp->servicename, "%s@%s",
1409 +                ud->svc == LUSTRE_GSS_SVC_MDS ?
1410 +               GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
1411 +                name);
1412 +        printerr(2, "constructed servicename: %s\n", clp->servicename);
1413 +        return 0;
1414 +}
1415  
1416  /*
1417   * this code uses the userland rpcsec gss library to create a krb5
1418 @@ -668,27 +910,78 @@ int create_auth_rpc_client(struct clnt_i
1419  void
1420  handle_krb5_upcall(struct clnt_info *clp)
1421  {
1422 -       uid_t                   uid;
1423 -       CLIENT                  *rpc_clnt = NULL;
1424 -       AUTH                    *auth = NULL;
1425 -       struct authgss_private_data pd;
1426 -       gss_buffer_desc         token;
1427 +       pid_t                   pid;
1428 +       gss_buffer_desc         token = { 0, NULL };
1429 +       struct lgssd_upcall_data updata;
1430 +       struct lustre_gss_data  lgd;
1431         char                    **credlist = NULL;
1432         char                    **ccname;
1433 +       int                     read_rc;
1434  
1435 -       printerr(1, "handling krb5 upcall\n");
1436 +       printerr(2, "handling krb5 upcall\n");
1437  
1438 -       token.length = 0;
1439 -       token.value = NULL;
1440 -       memset(&pd, 0, sizeof(struct authgss_private_data));
1441 +       memset(&lgd, 0, sizeof(lgd));
1442 +       lgd.lgd_rpc_err = -EPERM; /* default error code */
1443  
1444 -       if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
1445 -               printerr(0, "WARNING: failed reading uid from krb5 "
1446 +       read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
1447 +       if (read_rc < 0) {
1448 +               printerr(0, "WARNING: failed reading from krb5 "
1449                             "upcall pipe: %s\n", strerror(errno));
1450 -               goto out;
1451 +               return;
1452 +       } else if (read_rc != sizeof(updata)) {
1453 +               printerr(0, "upcall data mismatch: length %d, expect %d\n",
1454 +                        read_rc, sizeof(updata));
1455 +
1456 +               /* the sequence number must be the first field. if read >= 4
1457 +                * bytes then we know at least sequence is fine, try to send
1458 +                * error notification nicely.
1459 +                */
1460 +               if (read_rc >= 4)
1461 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1462 +               return;
1463 +       }
1464 +
1465 +       /* fork child process */
1466 +       pid = fork();
1467 +       if (pid < 0) {
1468 +               printerr(0, "can't fork: %s\n", strerror(errno));
1469 +               do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1470 +               return;
1471 +       } else if (pid > 0) {
1472 +               printerr(2, "forked child process: %d\n", pid);
1473 +               return;
1474 +       }
1475 +
1476 +       printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, "
1477 +                "pag %llx, obd %s\n", updata.seq, updata.uid, updata.svc,
1478 +                updata.nid, updata.pag, updata.obd);
1479 +
1480 +       /* XXX in kernel pag is defined as "unsigned long", which might
1481 +        * not keep original signed value after converted to u64.
1482 +        */
1483 +       if (updata.pag != updata.uid &&
1484 +           ((updata.pag == 0xffffffffffffffffULL) ||
1485 +            (updata.pag == 0xffffffff))) {
1486 +               printerr(0, "uid %u: pag %llx not allowed\n",
1487 +                        updata.uid, updata.pag);
1488 +               lgd.lgd_rpc_err = -EPROTO;
1489 +               goto out_return_error;
1490         }
1491  
1492 -       if (uid == 0) {
1493 +       if (updata.svc != LUSTRE_GSS_SVC_MDS &&
1494 +           updata.svc != LUSTRE_GSS_SVC_OSS) {
1495 +               printerr(0, "invalid svc %d\n", updata.svc);
1496 +               lgd.lgd_rpc_err = -EPROTO;
1497 +               goto out_return_error;
1498 +       }
1499 +       updata.obd[sizeof(updata.obd)-1] = '\0';
1500 +
1501 +       if (construct_service_name(clp, &updata)) {
1502 +               printerr(0, "failed to construct service name\n");
1503 +               goto out_return_error;
1504 +       }
1505 +
1506 +       if (updata.uid == 0) {
1507                 int success = 0;
1508  
1509                 /*
1510 @@ -696,75 +989,66 @@ handle_krb5_upcall(struct clnt_info *clp
1511                  * of them until one works or we've tried them all
1512                  */
1513                 if (gssd_get_krb5_machine_cred_list(&credlist)) {
1514 -                       printerr(0, "WARNING: Failed to obtain machine "
1515 -                                   "credentials for connection to "
1516 -                                   "server %s\n", clp->servername);
1517 -                               goto out_return_error;
1518 +                       printerr(0, "ERROR: Failed to obtain machine "
1519 +                                   "credentials for %s\n", clp->servicename);
1520 +                       goto out_return_error;
1521                 }
1522                 for (ccname = credlist; ccname && *ccname; ccname++) {
1523                         gssd_setup_krb5_machine_gss_ccache(*ccname);
1524 -                       if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1525 -                                                   AUTHTYPE_KRB5)) == 0) {
1526 +                       if ((gssd_create_lgd(clp, &lgd, &updata,
1527 +                                            AUTHTYPE_KRB5)) == 0) {
1528                                 /* Success! */
1529                                 success++;
1530                                 break;
1531                         }
1532                         printerr(2, "WARNING: Failed to create krb5 context "
1533                                     "for user with uid %d with credentials "
1534 -                                   "cache %s for server %s\n",
1535 -                                uid, *ccname, clp->servername);
1536 +                                   "cache %s for service %s\n",
1537 +                                updata.uid, *ccname, clp->servicename);
1538                 }
1539                 gssd_free_krb5_machine_cred_list(credlist);
1540                 if (!success) {
1541 -                       printerr(0, "WARNING: Failed to create krb5 context "
1542 +                       printerr(0, "ERROR: Failed to create krb5 context "
1543                                     "for user with uid %d with any "
1544 -                                   "credentials cache for server %s\n",
1545 -                                uid, clp->servername);
1546 +                                   "credentials cache for service %s\n",
1547 +                                updata.uid, clp->servicename);
1548                         goto out_return_error;
1549                 }
1550         }
1551         else {
1552                 /* Tell krb5 gss which credentials cache to use */
1553 -               gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
1554 +               gssd_setup_krb5_user_gss_ccache(updata.pag, updata.uid,
1555 +                                               clp->servicename);
1556  
1557 -               if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1558 -                                                       AUTHTYPE_KRB5)) != 0) {
1559 +               if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
1560                         printerr(0, "WARNING: Failed to create krb5 context "
1561 -                                   "for user with uid %d for server %s\n",
1562 -                                uid, clp->servername);
1563 +                                   "for user with uid %d for service %s\n",
1564 +                                updata.uid, clp->servicename);
1565                         goto out_return_error;
1566                 }
1567         }
1568  
1569 -       if (!authgss_get_private_data(auth, &pd)) {
1570 -               printerr(0, "WARNING: Failed to obtain authentication "
1571 -                           "data for user with uid %d for server %s\n",
1572 -                        uid, clp->servername);
1573 -               goto out_return_error;
1574 -       }
1575 -
1576 -       if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
1577 +       if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
1578                 printerr(0, "WARNING: Failed to serialize krb5 context for "
1579 -                           "user with uid %d for server %s\n",
1580 -                        uid, clp->servername);
1581 +                           "user with uid %d for service %s\n",
1582 +                        updata.uid, clp->servicename);
1583                 goto out_return_error;
1584         }
1585  
1586 -       do_downcall(clp->krb5_fd, uid, &pd, &token);
1587 +       printerr(1, "refreshed: %u@%s for %s\n",
1588 +                updata.uid, updata.obd, clp->servicename);
1589 +       do_downcall(clp->krb5_fd, &updata, &lgd, &token);
1590  
1591  out:
1592         if (token.value)
1593                 free(token.value);
1594 -       if (pd.pd_ctx_hndl.length != 0)
1595 -               authgss_free_private_data(&pd);
1596 -       if (auth)
1597 -               AUTH_DESTROY(auth);
1598 -       if (rpc_clnt)
1599 -               clnt_destroy(rpc_clnt);
1600 -       return;
1601 +
1602 +       gssd_free_lgd(&lgd);
1603 +       exit(0); /* i'm child process */
1604  
1605  out_return_error:
1606 -       do_error_downcall(clp->krb5_fd, uid, -1);
1607 +       do_error_downcall(clp->krb5_fd, updata.seq,
1608 +                         lgd.lgd_rpc_err, lgd.lgd_gss_err);
1609         goto out;
1610  }
1611  
1612 @@ -775,6 +1059,7 @@ out_return_error:
1613  void
1614  handle_spkm3_upcall(struct clnt_info *clp)
1615  {
1616 +#if 0
1617         uid_t                   uid;
1618         CLIENT                  *rpc_clnt = NULL;
1619         AUTH                    *auth = NULL;
1620 @@ -826,4 +1111,5 @@ out:
1621  out_return_error:
1622         do_error_downcall(clp->spkm3_fd, uid, -1);
1623         goto out;
1624 +#endif
1625  }
1626 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.c nfs-utils-1.0.10/utils/gssd/gss_util.c
1627 --- nfs-utils-1.0.10.orig/utils/gssd/gss_util.c 2006-08-07 00:40:50.000000000 -0600
1628 +++ nfs-utils-1.0.10/utils/gssd/gss_util.c      2006-12-15 15:12:23.000000000 -0700
1629 @@ -87,9 +87,16 @@
1630  #ifdef HAVE_COM_ERR_H
1631  #include <com_err.h>
1632  #endif
1633 +#include "lsupport.h"
1634  
1635  /* Global gssd_credentials handle */
1636 -gss_cred_id_t gssd_creds;
1637 +gss_cred_id_t  gssd_cred_mds;
1638 +gss_cred_id_t  gssd_cred_oss;
1639 +int            gssd_cred_mds_valid = 0;
1640 +int            gssd_cred_oss_valid = 0;
1641 +
1642 +char *mds_local_realm = NULL;
1643 +char *oss_local_realm = NULL;
1644  
1645  gss_OID g_mechOid = GSS_C_NULL_OID;;
1646  
1647 @@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
1648         display_status_2(msg, maj_stat, min_stat, mech);
1649  }
1650  
1651 -int
1652 -gssd_acquire_cred(char *server_name)
1653 +static
1654 +int extract_realm_name(gss_buffer_desc *name, char **realm)
1655 +{
1656 +        char *sname, *c;
1657 +       int   rc = 0;
1658 +
1659 +        sname = malloc(name->length + 1);
1660 +        if (!sname) {
1661 +                printerr(0, "out of memory\n");
1662 +                return -ENOMEM;
1663 +        }
1664 +
1665 +        memcpy(sname, name->value, name->length);
1666 +        sname[name->length] = '\0';
1667 +        printerr(1, "service principal: %s\n", sname);
1668 +
1669 +        c = strchr(sname, '@');
1670 +        if (!c) {
1671 +               printerr(2, "no realm found in principal, use default\n");
1672 +               *realm = strdup(this_realm);
1673 +                if (!*realm) {
1674 +                        printerr(0, "failed to duplicate default realm\n");
1675 +                        rc = -ENOMEM;
1676 +                }
1677 +        } else {
1678 +                c++;
1679 +                *realm = strdup(c);
1680 +                if (!*realm) {
1681 +                        printerr(0, "failed to duplicated realm\n");
1682 +                        rc = -ENOMEM;
1683 +                }
1684 +        }
1685 +        free(sname);
1686 +
1687 +        return rc;
1688 +}
1689 +
1690 +static
1691 +int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
1692 +                     char **local_realm, int *valid)
1693  {
1694         gss_buffer_desc name;
1695         gss_name_t target_name;
1696         u_int32_t maj_stat, min_stat;
1697         u_int32_t ignore_maj_stat, ignore_min_stat;
1698 +       gss_OID name_type;
1699         gss_buffer_desc pbuf;
1700  
1701 +       *valid = 0;
1702 +
1703         name.value = (void *)server_name;
1704         name.length = strlen(server_name);
1705  
1706 @@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
1707  
1708         if (maj_stat != GSS_S_COMPLETE) {
1709                 pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
1710 -               return (FALSE);
1711 +               return -1;
1712 +       }
1713 +
1714 +       maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
1715 +       if (maj_stat != GSS_S_COMPLETE) {
1716 +               pgsserr(0, maj_stat, min_stat, g_mechOid);
1717 +               return -1;
1718         }
1719 +       if (extract_realm_name(&name, local_realm))
1720 +               return -1;
1721  
1722         maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
1723                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
1724 -                       &gssd_creds, NULL, NULL);
1725 +                       cred, NULL, NULL);
1726  
1727         if (maj_stat != GSS_S_COMPLETE) {
1728                 pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
1729 @@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
1730                         ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
1731                                                              &pbuf);
1732                 }
1733 -       }
1734 +       } else
1735 +               *valid = 1;
1736  
1737         ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
1738  
1739 -       return (maj_stat == GSS_S_COMPLETE);
1740 +       if (maj_stat != GSS_S_COMPLETE)
1741 +               return -1;
1742 +       return 0;
1743 +}
1744 +
1745 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
1746 +{
1747 +        if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
1748 +                              &mds_local_realm, &gssd_cred_mds_valid)) {
1749 +                if (must_srv_mds)
1750 +                        return -1;
1751 +        }
1752 +
1753 +        if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
1754 +                              &oss_local_realm, &gssd_cred_oss_valid)) {
1755 +                if (must_srv_oss)
1756 +                        return -1;
1757 +        }
1758 +
1759 +        if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
1760 +                printerr(0, "can't obtain both mds & oss creds, exit\n");
1761 +                return -1;
1762 +        }
1763 +
1764 +       if (gssd_cred_mds_valid)
1765 +               printerr(0, "Ready to serve Lustre MDS in realm %s\n",
1766 +                        mds_local_realm ? mds_local_realm : "N/A");
1767 +       if (gssd_cred_oss_valid)
1768 +               printerr(0, "Ready to serve Lustre OSS in realm %s\n",
1769 +                        oss_local_realm ? oss_local_realm : "N/A");
1770 +
1771 +        return 0;
1772 +}
1773 +
1774 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
1775 +{
1776 +        switch (lustre_svc) {
1777 +        case LUSTRE_GSS_SVC_MDS:
1778 +                if (!gssd_cred_mds_valid) {
1779 +                        printerr(0, "ERROR: service cred for mds not ready\n");
1780 +                        return NULL;
1781 +                }
1782 +               printerr(2, "select mds service cred\n");
1783 +                return gssd_cred_mds;
1784 +        case LUSTRE_GSS_SVC_OSS:
1785 +                if (!gssd_cred_oss_valid) {
1786 +                        printerr(0, "ERROR: service cred for oss not ready\n");
1787 +                        return NULL;
1788 +                }
1789 +               printerr(2, "select oss service cred\n");
1790 +                return gssd_cred_oss;
1791 +        default:
1792 +                printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
1793 +        }
1794 +
1795 +        return NULL;
1796  }
1797  
1798  int gssd_check_mechs(void)
1799 @@ -249,3 +361,42 @@ out:
1800         return retval;
1801  }
1802  
1803 +/*********************************
1804 + * FIXME should be in krb5_util.c
1805 + *********************************/
1806 +
1807 +#include "krb5_util.h"
1808 +
1809 +/* realm of this node */
1810 +char *this_realm = NULL;
1811 +
1812 +int gssd_get_local_realm(void)
1813 +{
1814 +       krb5_context context = NULL;
1815 +       krb5_error_code code;
1816 +       int retval = -1;
1817 +
1818 +       if (this_realm != NULL)
1819 +               return 0;
1820 +
1821 +       code = krb5_init_context(&context);
1822 +       if (code) {
1823 +               printerr(0, "ERROR: get default realm: init ctx: %s\n",
1824 +                        error_message(code));
1825 +               goto out;
1826 +       }
1827 +
1828 +       code = krb5_get_default_realm(context, &this_realm);
1829 +       if (code) {
1830 +               printerr(0, "ERROR: get default realm: %s\n",
1831 +                        error_message(code));
1832 +               goto out;
1833 +       }
1834 +       retval = 0;
1835 +
1836 +       printerr(1, "Local realm: %s\n", this_realm);
1837 +out:
1838 +       krb5_free_context(context);
1839 +       return retval;
1840 +}
1841 +
1842 diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.h nfs-utils-1.0.10/utils/gssd/gss_util.h
1843 --- nfs-utils-1.0.10.orig/utils/gssd/gss_util.h 2006-08-07 00:40:50.000000000 -0600
1844 +++ nfs-utils-1.0.10/utils/gssd/gss_util.h      2006-12-15 15:12:23.000000000 -0700
1845 @@ -32,14 +32,14 @@
1846  #define _GSS_UTIL_H_
1847  
1848  #include <stdlib.h>
1849 -#include <rpc/rpc.h>
1850  #include "write_bytes.h"
1851  
1852 +char *this_realm;
1853  extern gss_cred_id_t   gssd_creds;
1854  
1855 -int gssd_acquire_cred(char *server_name);
1856  void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
1857         const gss_OID mech);
1858  int gssd_check_mechs(void);
1859 +int gssd_get_local_realm(void);
1860  
1861  #endif /* _GSS_UTIL_H_ */
1862 diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c nfs-utils-1.0.10/utils/gssd/krb5_util.c
1863 --- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c        2006-11-15 21:26:08.000000000 -0700
1864 +++ nfs-utils-1.0.10/utils/gssd/krb5_util.c     2006-12-15 15:12:23.000000000 -0700
1865 @@ -99,12 +99,15 @@
1866  #include <rpc/rpc.h>
1867  #include <sys/types.h>
1868  #include <sys/stat.h>
1869 +#include <sys/utsname.h>
1870  #include <sys/socket.h>
1871  #include <arpa/inet.h>
1872  
1873 +#include <unistd.h>
1874  #include <stdio.h>
1875  #include <stdlib.h>
1876  #include <string.h>
1877 +#include <netdb.h>
1878  #include <dirent.h>
1879  #include <fcntl.h>
1880  #include <errno.h>
1881 @@ -114,7 +117,6 @@
1882  #include <gssapi/gssapi_krb5.h>
1883  #endif
1884  #include <krb5.h>
1885 -#include <rpc/auth_gss.h>
1886  
1887  #include "gssd.h"
1888  #include "err_util.h"
1889 @@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
1890  int num_krb5_enctypes = 0;
1891  krb5_enctype *krb5_enctypes = NULL;
1892  
1893 +/* credential expire time in advance */
1894 +unsigned long machine_cred_expire_advance = 300; /* 5 mins */
1895 +
1896  /*==========================*/
1897  /*===  Internal routines ===*/
1898  /*==========================*/
1899 @@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
1900  static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
1901  static int gssd_get_single_krb5_cred(krb5_context context,
1902                 krb5_keytab kt, struct gssd_k5_kt_princ *ple);
1903 -static int gssd_have_realm_ple(void *realm);
1904  static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
1905                 char *kt_name);
1906  
1907  /*
1908 + * convenient macros, these perhaps need further cleanup
1909 + */
1910 +#ifdef HAVE_KRB5
1911 +
1912 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
1913 +       (                                                                      \
1914 +        (kte).principal->data[0].length == (sizeof(name)-1) &&                \
1915 +        strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0   \
1916 +       )
1917 +#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                    \
1918 +               krb5_free_unparsed_name((ctx), (name));
1919 +#define KRB5_STRDUP(str)                                                      \
1920 +               strndup((str).data, (str).length)
1921 +#define KRB5_STRCMP(str, name)                                                \
1922 +       (                                                                      \
1923 +        (str)->length != strlen(name) ||                                      \
1924 +        strncmp((str)->data, (name), (str)->length) != 0                      \
1925 +       )
1926 +#define KRB5_STRCASECMP(str, name)                                            \
1927 +       (                                                                      \
1928 +        (str)->length != strlen(name) ||                                      \
1929 +        strncasecmp((str)->data, (name), (str)->length) != 0                  \
1930 +       )
1931 +
1932 +#else /* !HAVE_KRB5 */
1933 +
1934 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
1935 +       (                                                                      \
1936 +        strlen((kte).principal->name.name_string.val[0]) ==                   \
1937 +        (sizeof(name)-1) &&                                                   \
1938 +        strncmp(kte.principal->name.name_string.val[0], (name),               \
1939 +                sizeof(name)-1) == 0                                          \
1940 +       )
1941 +#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                    \
1942 +               free(pname);
1943 +#define KRB5_STRDUP(str)                                                      \
1944 +               strdup(str)
1945 +#define KRB5_STRCMP(str, name)                                                \
1946 +               strcmp((str), (name))
1947 +#define KRB5_STRCASECMP(str, name)                                            \
1948 +               strcmp((str), (name))
1949 +
1950 +#endif /* HAVE_KRB5 */
1951 +
1952 +/*
1953   * Called from the scandir function to weed out potential krb5
1954   * credentials cache files
1955   *
1956 @@ -294,7 +343,7 @@ gssd_get_single_krb5_cred(krb5_context c
1957  
1958         memset(&my_creds, 0, sizeof(my_creds));
1959  
1960 -       if (ple->ccname && ple->endtime > now) {
1961 +       if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
1962                 printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
1963                          ple->ccname, ple->endtime);
1964                 code = 0;
1965 @@ -325,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c
1966                             "principal '%s' from keytab '%s'\n",
1967                          error_message(code),
1968                          pname ? pname : "<unparsable>", kt_name);
1969 -#ifdef HAVE_KRB5
1970 -               if (pname) krb5_free_unparsed_name(context, pname);
1971 -#else
1972 -               if (pname) free(pname);
1973 -#endif
1974 +               if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
1975                 goto out;
1976         }
1977  
1978 @@ -378,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
1979         return (code);
1980  }
1981  
1982 -/*
1983 - * Determine if we already have a ple for the given realm
1984 - *
1985 - * Returns:
1986 - *     0 => no ple found for given realm
1987 - *     1 => found ple for given realm
1988 - */
1989 -static int
1990 -gssd_have_realm_ple(void *r)
1991 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
1992  {
1993         struct gssd_k5_kt_princ *ple;
1994  #ifdef HAVE_KRB5
1995 @@ -396,18 +433,76 @@ gssd_have_realm_ple(void *r)
1996  #endif
1997  
1998         for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
1999 -#ifdef HAVE_KRB5
2000 -               if ((realm->length == strlen(ple->realm)) &&
2001 -                   (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2002 -#else
2003 -               if (strcmp(realm, ple->realm) == 0) {
2004 -#endif
2005 -                   return 1;
2006 -               }
2007 +               if (KRB5_STRCMP(realm, ple->realm) == 0)
2008 +                   return ple;
2009 +       }
2010 +       return NULL;
2011 +}
2012 +
2013 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2014 +{
2015 +       if (ple->princ)
2016 +               krb5_free_principal(kctx, ple->princ);
2017 +       if (ple->realm)
2018 +               free(ple->realm);
2019 +       if (ple->ccname)
2020 +               free(ple->ccname);
2021 +       free(ple);
2022 +}
2023 +
2024 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2025 +{
2026 +       struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2027 +       struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
2028 +
2029 +       for (; ent; prev = &ent->next, ent = ent->next) {
2030 +               if (ent != ple)
2031 +                       continue;
2032 +
2033 +               *prev = ent->next;
2034 +               gssd_free_ple(kctx, ent);
2035 +               return 1;
2036         }
2037         return 0;
2038  }
2039  
2040 +static
2041 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2042 +                                        krb5_principal principal)
2043 +{
2044 +       struct gssd_k5_kt_princ *ple;
2045 +       krb5_error_code          code;
2046 +
2047 +       ple = malloc(sizeof(*ple));
2048 +       if (ple == NULL) {
2049 +               printerr(0, "ERROR: could not allocate storage "
2050 +                           "for principal list entry\n");
2051 +               return NULL;
2052 +       }
2053 +
2054 +       memset(ple, 0, sizeof(*ple));
2055 +
2056 +       ple->realm = KRB5_STRDUP(principal->realm);
2057 +       if (ple->realm == NULL) {
2058 +               printerr(0, "ERROR: not enough memory while copying realm to "
2059 +                           "principal list entry\n");
2060 +               goto err_free;
2061 +       }
2062 +
2063 +       code = krb5_copy_principal(kctx, principal, &ple->princ);
2064 +       if (code) {
2065 +               printerr(0, "ERROR: %s while copying principal "
2066 +                           "to principal list entry\n",
2067 +                        error_message(code));
2068 +               goto err_free;
2069 +       }
2070 +
2071 +       return ple;
2072 +err_free:
2073 +       gssd_free_ple(kctx, ple);
2074 +       return NULL;
2075 +}
2076 +
2077  /*
2078   * Process the given keytab file and create a list of principals we
2079   * might use to perform mount operations.
2080 @@ -451,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co
2081                 }
2082                 printerr(2, "Processing keytab entry for principal '%s'\n",
2083                          pname);
2084 -#ifdef HAVE_KRB5
2085 -               if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
2086 -                    (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
2087 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2088 -#else
2089 -               if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
2090 -                    (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
2091 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2092 -                             
2093 -#endif
2094 -                    (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
2095 -                       printerr(2, "We will use this entry (%s)\n", pname);
2096 -                       ple = malloc(sizeof(struct gssd_k5_kt_princ));
2097 -                       if (ple == NULL) {
2098 -                               printerr(0, "ERROR: could not allocate storage "
2099 -                                           "for principal list entry\n");
2100 -#ifdef HAVE_KRB5
2101 -                               krb5_free_unparsed_name(context, pname);
2102 -#else
2103 -                               free(pname);
2104 -#endif
2105 -                               retval = ENOMEM;
2106 -                               goto out;
2107 +
2108 +               /* mds service entry:
2109 +                *   - hostname and realm should match this node
2110 +                *   - replace existing non-mds entry of this realm
2111 +                */
2112 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
2113 +                       krb5_principal princ = kte.principal;
2114 +                       krb5_data *princ_host;
2115 +                       struct utsname utsbuf;
2116 +                       struct hostent *host;
2117 +
2118 +                       if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2119 +                                           this_realm) != 0) {
2120 +                               printerr(2, "alien mds service entry, skip\n");
2121 +                               goto next;
2122                         }
2123 -                       /* These will be filled in later */
2124 -                       ple->next = NULL;
2125 -                       ple->ccname = NULL;
2126 -                       ple->endtime = 0;
2127 -                       if ((ple->realm =
2128 -#ifdef HAVE_KRB5
2129 -                               strndup(kte.principal->realm.data,
2130 -                                       kte.principal->realm.length))
2131 -#else
2132 -                               strdup(kte.principal->realm))
2133 -#endif
2134 -                                       == NULL) {
2135 -                               printerr(0, "ERROR: %s while copying realm to "
2136 -                                           "principal list entry\n",
2137 -                                        "not enough memory");
2138 -#ifdef HAVE_KRB5
2139 -                               krb5_free_unparsed_name(context, pname);
2140 -#else
2141 -                               free(pname);
2142 -#endif
2143 -                               retval = ENOMEM;
2144 -                               goto out;
2145 +
2146 +                       princ_host = krb5_princ_component(context, princ, 1);
2147 +                       if (princ_host == NULL) {
2148 +                               printerr(2, "mds service entry: no hostname in "
2149 +                                        "principal, skip\n");
2150 +                               goto next;
2151                         }
2152 -                       if ((code = krb5_copy_principal(context,
2153 -                                       kte.principal, &ple->princ))) {
2154 -                               printerr(0, "ERROR: %s while copying principal "
2155 -                                           "to principal list entry\n",
2156 -                                       error_message(code));
2157 -#ifdef HAVE_KRB5
2158 -                               krb5_free_unparsed_name(context, pname);
2159 -#else
2160 -                               free(pname);
2161 -#endif
2162 -                               retval = code;
2163 -                               goto out;
2164 +
2165 +                       if (uname(&utsbuf)) {
2166 +                               printerr(2, "mds service entry: unable to get "
2167 +                                        "UTS name, skip\n");
2168 +                               goto next;
2169                         }
2170 -                       if (gssd_k5_kt_princ_list == NULL)
2171 -                               gssd_k5_kt_princ_list = ple;
2172 -                       else {
2173 -                               ple->next = gssd_k5_kt_princ_list;
2174 -                               gssd_k5_kt_princ_list = ple;
2175 +                       host = gethostbyname(utsbuf.nodename);
2176 +                       if (host == NULL) {
2177 +                               printerr(2, "mds service entry: unable to get "
2178 +                                        "local hostname, skip\n");
2179 +                               goto next;
2180                         }
2181 -               }
2182 -               else {
2183 +
2184 +                       if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
2185 +                               printerr(2, "mds service entry: hostname "
2186 +                                        "doesn't match: %s - %.*s, skip\n",
2187 +                                        host->h_name,
2188 +                                        princ_host->length, princ_host->data);
2189 +                               goto next;
2190 +                       }
2191 +
2192 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2193 +                       if (ple) {
2194 +                               if (ple->fl_mds) {
2195 +                                       printerr(2,"mds service entry: found a"
2196 +                                                "duplicated one, it's like a "
2197 +                                                "mis-configuration, skip\n");
2198 +                                       goto next;
2199 +                               }
2200 +
2201 +                               gssd_remove_ple(context, ple);
2202 +                               printerr(2, "mds service entry: replace an "
2203 +                                        "existed non-mds one\n");
2204 +                       }
2205 +               } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2206 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2207 +                       if (ple) {
2208 +                               if (ple->fl_mds || ple->fl_root) {
2209 +                                       printerr(2, "root entry: found a "
2210 +                                                "existed %s entry, skip\n",
2211 +                                                ple->fl_mds ? "mds" : "root");
2212 +                                       goto next;
2213 +                               }
2214 +
2215 +                               gssd_remove_ple(context, ple);
2216 +                               printerr(2, "root entry: replace an existed "
2217 +                                        "non-mds non-root one\n");
2218 +                       }
2219 +               } else {
2220                         printerr(2, "We will NOT use this entry (%s)\n",
2221                                 pname);
2222 +                       goto next;
2223                 }
2224 -#ifdef HAVE_KRB5
2225 -               krb5_free_unparsed_name(context, pname);
2226 -#else
2227 -               free(pname);
2228 -#endif
2229 +
2230 +               /* construct ple */
2231 +               printerr(2, "We will use this entry (%s)\n", pname);
2232 +               ple = gssd_create_ple(context, kte.principal);
2233 +               if (ple == NULL) {
2234 +                       KRB5_FREE_UNPARSED_NAME(context, pname);
2235 +                       goto out;
2236 +               }
2237 +
2238 +               /* add proper flags */
2239 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2240 +                       ple->fl_mds = 1;
2241 +               else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2242 +                       ple->fl_root = 1;
2243 +
2244 +               /* enqueue */
2245 +               if (gssd_k5_kt_princ_list == NULL)
2246 +                       gssd_k5_kt_princ_list = ple;
2247 +               else {
2248 +                       ple->next = gssd_k5_kt_princ_list;
2249 +                       gssd_k5_kt_princ_list = ple;
2250 +               }
2251 + next:
2252 +               KRB5_FREE_UNPARSED_NAME(context, pname);
2253         }
2254  
2255         if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
2256 @@ -634,14 +753,21 @@ parse_enctypes(char *enctypes)
2257   *     void
2258   */
2259  void
2260 -gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
2261 +gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername)
2262  {
2263         char                    buf[MAX_NETOBJ_SZ];
2264         struct dirent           *d;
2265  
2266 -       printerr(2, "getting credentials for client with uid %u for "
2267 -                   "server %s\n", uid, servername);
2268 +       printerr(2, "getting credentials for client with pag %llx/uid %u for "
2269 +                   "server %s\n", pag, uid, servername);
2270         memset(buf, 0, sizeof(buf));
2271 +
2272 +       if (pag != uid) {
2273 +               snprintf(buf, sizeof(buf), "FILE:%s/%spag_%llx",
2274 +                        ccachedir, GSSD_DEFAULT_CRED_PREFIX, pag);
2275 +               goto set_ccname;
2276 +       }
2277 +
2278         if (gssd_find_existing_krb5_ccache(uid, &d)) {
2279                 snprintf(buf, sizeof(buf), "FILE:%s/%s",
2280                         ccachedir, d->d_name);
2281 @@ -652,6 +778,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
2282                         ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid);
2283         printerr(2, "using %s as credentials cache for client with "
2284                     "uid %u for server %s\n", buf, uid, servername);
2285 +set_ccname:
2286         gssd_set_krb5_ccache_name(buf);
2287  }
2288  
2289 @@ -702,7 +829,7 @@ gssd_refresh_krb5_machine_creds(void)
2290                 goto out;
2291         }
2292  
2293 -       printerr(1, "Using keytab file '%s'\n", keytabfile);
2294 +       printerr(2, "Using keytab file '%s'\n", keytabfile);
2295  
2296         if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
2297                 printerr(0, "ERROR: %s while resolving keytab '%s'\n",
2298 @@ -717,12 +844,12 @@ gssd_refresh_krb5_machine_creds(void)
2299                 if (gssd_k5_kt_princ_list == NULL) {
2300                         printerr(0, "ERROR: No usable keytab entries found in "
2301                                     "keytab '%s'\n", keytabfile);
2302 -                       printerr(0, "Do you have a valid keytab entry for "
2303 -                                   "%s/<your.host>@<YOUR.REALM> in "
2304 +                       printerr(0, "You must have a valid keytab entry for "
2305 +                                   "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
2306 +                                   "and %s@<YOUR.REALM> on client nodes, in "
2307                                     "keytab file %s ?\n",
2308 -                                   GSSD_SERVICE_NAME, keytabfile);
2309 -                       printerr(0, "Continuing without (machine) credentials "
2310 -                                   "- nfs4 mounts with Kerberos will fail\n");
2311 +                                   GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
2312 +                                   keytabfile);
2313                 }
2314         }
2315  
2316 @@ -872,6 +999,7 @@ gssd_destroy_krb5_machine_creds(void)
2317         krb5_free_context(context);
2318  }
2319  
2320 +#if 0
2321  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2322  /*
2323   * this routine obtains a credentials handle via gss_acquire_cred()
2324 @@ -927,6 +1055,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2325         return 0;
2326  }
2327  #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2328 +#endif
2329  
2330  /*
2331   * Obtain supported enctypes from kernel.
2332 diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h nfs-utils-1.0.10/utils/gssd/krb5_util.h
2333 --- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h        2006-11-15 21:26:08.000000000 -0700
2334 +++ nfs-utils-1.0.10/utils/gssd/krb5_util.h     2006-12-15 15:12:23.000000000 -0700
2335 @@ -10,13 +10,15 @@
2336  struct gssd_k5_kt_princ {
2337         struct gssd_k5_kt_princ *next;
2338         krb5_principal princ;
2339 +       unsigned int    fl_root:1,
2340 +                       fl_mds:1;
2341         char *ccname;
2342         char *realm;
2343         krb5_timestamp endtime;
2344  };
2345  
2346  
2347 -void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
2348 +void gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername);
2349  int  gssd_get_krb5_machine_cred_list(char ***list);
2350  int  gssd_refresh_krb5_machine_creds(void);
2351  void gssd_free_krb5_machine_cred_list(char **list);
2352 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2353  void gssd_obtain_kernel_krb5_info(void);
2354  
2355  
2356 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2357 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2358 -#endif
2359 -
2360  #endif /* KRB5_UTIL_H */
2361 diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.c nfs-utils-1.0.10/utils/gssd/lsupport.c
2362 --- nfs-utils-1.0.10.orig/utils/gssd/lsupport.c 2006-11-15 21:41:25.000000000 -0700
2363 +++ nfs-utils-1.0.10/utils/gssd/lsupport.c      2006-12-15 15:12:23.000000000 -0700
2364 @@ -0,0 +1,782 @@
2365 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2366 + * vim:expandtab:shiftwidth=8:tabstop=8:
2367 + *
2368 + *  Copyright (c) 2005 Cluster File Systems, Inc.
2369 + *
2370 + *   This file is part of Lustre, http://www.lustre.org.
2371 + *
2372 + *   Lustre is free software; you can redistribute it and/or
2373 + *   modify it under the terms of version 2 of the GNU General Public
2374 + *   License as published by the Free Software Foundation.
2375 + *
2376 + *   Lustre is distributed in the hope that it will be useful,
2377 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
2378 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2379 + *   GNU General Public License for more details.
2380 + *
2381 + *   You should have received a copy of the GNU General Public License
2382 + *   along with Lustre; if not, write to the Free Software
2383 + *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2384 + */
2385 +
2386 +#ifndef _GNU_SOURCE
2387 +#define _GNU_SOURCE
2388 +#endif
2389 +#include "config.h"
2390 +#include <sys/param.h>
2391 +#include <sys/utsname.h>
2392 +#include <sys/stat.h>
2393 +#include <sys/socket.h>
2394 +#include <arpa/inet.h>
2395 +#include <sys/types.h>
2396 +#include <sys/ipc.h>
2397 +#include <sys/sem.h>
2398 +
2399 +#include <stdio.h>
2400 +#include <stdlib.h>
2401 +#include <pwd.h>
2402 +#include <grp.h>
2403 +#include <string.h>
2404 +#include <dirent.h>
2405 +#include <poll.h>
2406 +#include <fcntl.h>
2407 +#include <signal.h>
2408 +#include <unistd.h>
2409 +#include <errno.h>
2410 +#include <assert.h>
2411 +#ifdef HAVE_GETHOSTBYNAME
2412 +# include <netdb.h>
2413 +#endif
2414 +
2415 +#include "err_util.h"
2416 +#include "gssd.h"
2417 +#include "lsupport.h"
2418 +
2419 +/****************************************
2420 + * exclusive startup                    *
2421 + ****************************************/
2422 +
2423 +static struct __sem_s {
2424 +        char           *name;
2425 +        key_t           sem_key;
2426 +        int             sem_id;
2427 +} sems[2] = {
2428 +        [GSSD_CLI] = { "client",  0x3a92d473, 0 },
2429 +        [GSSD_SVC] = { "server",  0x3b92d473, 0 },
2430 +};
2431 +
2432 +void gssd_init_unique(int type)
2433 +{
2434 +        struct __sem_s *sem = &sems[type];
2435 +        struct sembuf   sembuf;
2436 +
2437 +        assert(type == GSSD_CLI || type == GSSD_SVC);
2438 +
2439 +again:
2440 +        sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
2441 +        if (sem->sem_id == -1) {
2442 +                if (errno != EEXIST) {
2443 +                        printerr(0, "Create sem: %s\n", strerror(errno));
2444 +                        exit(-1);
2445 +                }
2446 +
2447 +                /* already exist. Note there's still a small window racing
2448 +                 * with other processes, due to the stupid semaphore semantics.
2449 +                 */
2450 +                sem->sem_id = semget(sem->sem_key, 0, 0700);
2451 +                if (sem->sem_id == -1) {
2452 +                        if (errno == ENOENT) {
2453 +                                printerr(0, "another instance just exit, "
2454 +                                         "try again\n");
2455 +                                goto again;
2456 +                        }
2457 +
2458 +                        printerr(0, "Obtain sem: %s\n", strerror(errno));
2459 +                        exit(-1);
2460 +                }
2461 +        } else {
2462 +                int val = 1;
2463 +
2464 +                if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
2465 +                        printerr(0, "Initialize sem: %s\n",
2466 +                                 strerror(errno));
2467 +                        exit(-1);
2468 +                }
2469 +        }
2470 +
2471 +        sembuf.sem_num = 0;
2472 +        sembuf.sem_op = -1;
2473 +        sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
2474 +
2475 +        if (semop(sem->sem_id, &sembuf, 1) != 0) {
2476 +                if (errno == EAGAIN) {
2477 +                        printerr(0, "Another instance is running, exit\n");
2478 +                        exit(0);
2479 +                }
2480 +                printerr(0, "Grab sem: %s\n", strerror(errno));
2481 +                exit(0);
2482 +        }
2483 +
2484 +        printerr(2, "Successfully created %s global identity\n", sem->name);
2485 +}
2486 +
2487 +void gssd_exit_unique(int type)
2488 +{
2489 +        assert(type == GSSD_CLI || type == GSSD_SVC);
2490 +
2491 +        /*
2492 +         * do nothing. we can't remove the sem here, otherwise the race
2493 +         * window would be much bigger. So it's sad we have to leave the
2494 +         * sem in the system forever.
2495 +         */
2496 +}
2497 +
2498 +/****************************************
2499 + * client side resolvation:             *
2500 + *    lnd/netid/nid => hostname         *
2501 + ****************************************/
2502 +
2503 +char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
2504 +
2505 +typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
2506 +                               char *buf, int buflen);
2507 +
2508 +/* FIXME what about IPv6? */
2509 +static
2510 +int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2511 +                         char *buf, int buflen)
2512 +{
2513 +        struct hostent  *ent;
2514 +
2515 +        addr = htonl(addr);
2516 +        ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
2517 +        if (!ent) {
2518 +                printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
2519 +                return -1;
2520 +        }
2521 +        if (strlen(ent->h_name) >= buflen) {
2522 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
2523 +                return -1;
2524 +        }
2525 +        strcpy(buf, ent->h_name);
2526 +
2527 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
2528 +                 lnd, net, addr, buf);
2529 +        return 0;
2530 +}
2531 +
2532 +static
2533 +int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2534 +                       char *buf, int buflen)
2535 +{
2536 +        struct utsname   uts;
2537 +        struct hostent  *ent;
2538 +
2539 +        if (addr) {
2540 +                printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
2541 +                return -1;
2542 +        }
2543 +
2544 +        if (uname(&uts)) {
2545 +                printerr(0, "%s: failed obtain local machine name\n", lnd);
2546 +                return -1;
2547 +        }
2548 +
2549 +        ent = gethostbyname(uts.nodename);
2550 +        if (!ent) {
2551 +                printerr(0, "%s: failed obtain canonical name of %s\n",
2552 +                         lnd, uts.nodename);
2553 +                return -1;
2554 +        }
2555 +
2556 +        if (strlen(ent->h_name) >= buflen) {
2557 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
2558 +                return -1;
2559 +        }
2560 +        strcpy(buf, ent->h_name);
2561 +
2562 +        printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
2563 +        return 0;
2564 +}
2565 +
2566 +static int is_space(char c)
2567 +{
2568 +        return (c == ' ' || c == '\t' || c == '\n');
2569 +}
2570 +
2571 +static
2572 +int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2573 +                          char *namebuf, int namebuflen)
2574 +{
2575 +        const int bufsize = PATH_MAX + 256;
2576 +        char buf[bufsize], *head, *tail;
2577 +        FILE *fghn;
2578 +
2579 +        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
2580 +        printerr(2, "cmd: %s\n", buf);
2581 +
2582 +        fghn = popen(buf, "r");
2583 +        if (fghn == NULL) {
2584 +                printerr(0, "failed to call %s\n", gethostname_ex);
2585 +                return -1;
2586 +        }
2587 +
2588 +        head = fgets(buf, bufsize, fghn);
2589 +        if (head == NULL) {
2590 +                printerr(0, "can't read from %s\n", gethostname_ex);
2591 +                return -1;
2592 +        }
2593 +        if (pclose(fghn) == -1)
2594 +                printerr(1, "pclose failed, continue\n");
2595 +
2596 +        /* trim head/tail space */
2597 +        while (is_space(*head))
2598 +                head++;
2599 +
2600 +        tail = head + strlen(head);
2601 +        if (tail <= head) {
2602 +                printerr(0, "no output from %s\n", gethostname_ex);
2603 +                return -1;
2604 +        }
2605 +        while (is_space(*(tail - 1)))
2606 +                tail--;
2607 +        if (tail <= head) {
2608 +                printerr(0, "output are all space from %s\n", gethostname_ex);
2609 +                return -1;
2610 +        }
2611 +        *tail = '\0';
2612 +
2613 +        /* start with '@' means error msg */
2614 +        if (head[0] == '@') {
2615 +                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
2616 +                return -1;
2617 +        }
2618 +
2619 +        if (tail - head > namebuflen) {
2620 +                printerr(0, "external hostname too long: %s\n", head);
2621 +                return -1;
2622 +        }
2623 +
2624 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
2625 +                 lnd, net, addr, head);
2626 +        strcpy(namebuf, head);
2627 +        return 0;
2628 +}
2629 +
2630 +static struct {
2631 +        char                    *name;
2632 +        lnd_nid2hostname_t      *nid2name;
2633 +} converter[LND_ENUM_END_MARKER] = {
2634 +        {"UNUSED0",     NULL},
2635 +        [QSWLND]        = { "QSWLND",   external_nid2hostname},
2636 +        [SOCKLND]       = { "SOCKLND",  socklnd_nid2hostname},
2637 +        [GMLND]         = { "GMLND",    external_nid2hostname},
2638 +        [PTLLND]        = { "PTLLND",   external_nid2hostname },
2639 +        [O2IBLND]       = { "O2IBLND",  external_nid2hostname },
2640 +        [CIBLND]        = { "CIBLND",   external_nid2hostname },
2641 +        [OPENIBLND]     = { "OPENIBLND",external_nid2hostname },
2642 +        [IIBLND]        = { "IIBLND",   external_nid2hostname },
2643 +        [LOLND]         = { "LOLND",    lolnd_nid2hostname },
2644 +        [RALND]         = { "RALND",    external_nid2hostname },
2645 +        [VIBLND]        = { "VIBLND",   external_nid2hostname },
2646 +};
2647 +
2648 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
2649 +{
2650 +        uint32_t lnd, net, addr;
2651 +
2652 +        addr = LNET_NIDADDR(nid);
2653 +        net = LNET_NIDNET(nid);
2654 +        lnd = LNET_NETTYP(net);
2655 +
2656 +        if (lnd >= LND_ENUM_END_MARKER) {
2657 +                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
2658 +                return -1;
2659 +        }
2660 +
2661 +        if (converter[lnd].nid2name == NULL) {
2662 +                printerr(0, "ERROR: %s converter not ready\n",
2663 +                        converter[lnd].name);
2664 +                return -1;
2665 +        }
2666 +
2667 +        return converter[lnd].nid2name(converter[lnd].name, net, addr,
2668 +                                       buf, buflen);
2669 +}
2670 +
2671 +
2672 +/****************************************
2673 + * lnet support routine                 *
2674 + * (from lnet/libcfs/nidstrings.c       *
2675 + ****************************************/
2676 +
2677 +#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
2678 +
2679 +static int  libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
2680 +static void libcfs_ip_addr2str(uint32_t addr, char *str);
2681 +static int  libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
2682 +static void libcfs_decnum_addr2str(uint32_t addr, char *str);
2683 +static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
2684 +static int  libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
2685 +
2686 +struct netstrfns {
2687 +        int          nf_type;
2688 +        char        *nf_name;
2689 +        char        *nf_modname;
2690 +        void       (*nf_addr2str)(uint32_t addr, char *str);
2691 +        int        (*nf_str2addr)(char *str, int nob, uint32_t *addr);
2692 +};
2693 +
2694 +static struct netstrfns  libcfs_netstrfns[] = {
2695 +        {/* .nf_type      */  LOLND,
2696 +         /* .nf_name      */  "lo",
2697 +         /* .nf_modname   */  "klolnd",
2698 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2699 +         /* .nf_str2addr  */  libcfs_lo_str2addr},
2700 +        {/* .nf_type      */  SOCKLND,
2701 +         /* .nf_name      */  "tcp",
2702 +         /* .nf_modname   */  "ksocklnd",
2703 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2704 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2705 +        {/* .nf_type      */  O2IBLND,
2706 +         /* .nf_name      */  "o2ib",
2707 +         /* .nf_modname   */  "ko2iblnd",
2708 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2709 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2710 +        {/* .nf_type      */  CIBLND,
2711 +         /* .nf_name      */  "cib",
2712 +         /* .nf_modname   */  "kciblnd",
2713 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2714 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2715 +        {/* .nf_type      */  OPENIBLND,
2716 +         /* .nf_name      */  "openib",
2717 +         /* .nf_modname   */  "kopeniblnd",
2718 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2719 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2720 +        {/* .nf_type      */  IIBLND,
2721 +         /* .nf_name      */  "iib",
2722 +         /* .nf_modname   */  "kiiblnd",
2723 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2724 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2725 +        {/* .nf_type      */  VIBLND,
2726 +         /* .nf_name      */  "vib",
2727 +         /* .nf_modname   */  "kviblnd",
2728 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2729 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2730 +        {/* .nf_type      */  RALND,
2731 +         /* .nf_name      */  "ra",
2732 +         /* .nf_modname   */  "kralnd",
2733 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2734 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2735 +        {/* .nf_type      */  QSWLND,
2736 +         /* .nf_name      */  "elan",
2737 +         /* .nf_modname   */  "kqswlnd",
2738 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2739 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2740 +        {/* .nf_type      */  GMLND,
2741 +         /* .nf_name      */  "gm",
2742 +         /* .nf_modname   */  "kgmlnd",
2743 +         /* .nf_addr2str  */  libcfs_hexnum_addr2str,
2744 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2745 +        {/* .nf_type      */  PTLLND,
2746 +         /* .nf_name      */  "ptl",
2747 +         /* .nf_modname   */  "kptllnd",
2748 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2749 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2750 +        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
2751 +        {/* .nf_type      */  -1},
2752 +};
2753 +
2754 +const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
2755 +
2756 +static int
2757 +libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
2758 +{
2759 +        *addr = 0;
2760 +        return 1;
2761 +}
2762 +
2763 +static void
2764 +libcfs_ip_addr2str(uint32_t addr, char *str)
2765 +{
2766 +        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
2767 +                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
2768 +                 (addr >> 8) & 0xff, addr & 0xff);
2769 +}
2770 +
2771 +/* CAVEAT EMPTOR XscanfX
2772 + * I use "%n" at the end of a sscanf format to detect trailing junk.  However
2773 + * sscanf may return immediately if it sees the terminating '0' in a string, so
2774 + * I initialise the %n variable to the expected length.  If sscanf sets it;
2775 + * fine, if it doesn't, then the scan ended at the end of the string, which is
2776 + * fine too :) */
2777 +
2778 +static int
2779 +libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
2780 +{
2781 +        int   a;
2782 +        int   b;
2783 +        int   c;
2784 +        int   d;
2785 +        int   n = nob;                          /* XscanfX */
2786 +
2787 +        /* numeric IP? */
2788 +        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
2789 +            n == nob &&
2790 +            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
2791 +            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
2792 +                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
2793 +                return 1;
2794 +        }
2795 +
2796 +#ifdef HAVE_GETHOSTBYNAME
2797 +        /* known hostname? */
2798 +        if (('a' <= str[0] && str[0] <= 'z') ||
2799 +            ('A' <= str[0] && str[0] <= 'Z')) {
2800 +                char *tmp;
2801 +
2802 +                tmp = malloc(nob + 1);
2803 +                if (tmp != NULL) {
2804 +                        struct hostent *he;
2805 +
2806 +                        memcpy(tmp, str, nob);
2807 +                        tmp[nob] = 0;
2808 +
2809 +                        he = gethostbyname(tmp);
2810 +
2811 +                        free(tmp);
2812 +                        tmp = NULL;
2813 +
2814 +                        if (he != NULL) {
2815 +                                uint32_t ip = *(uint32_t *)he->h_addr;
2816 +
2817 +                                *addr = ntohl(ip);
2818 +                                return 1;
2819 +                        }
2820 +                }
2821 +        }
2822 +#endif
2823 +        return 0;
2824 +}
2825 +
2826 +static void
2827 +libcfs_decnum_addr2str(uint32_t addr, char *str)
2828 +{
2829 +        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
2830 +}
2831 +
2832 +static void
2833 +libcfs_hexnum_addr2str(uint32_t addr, char *str)
2834 +{
2835 +        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
2836 +}
2837 +
2838 +static int
2839 +libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
2840 +{
2841 +        int     n;
2842 +
2843 +        n = nob;
2844 +        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
2845 +                return 1;
2846 +
2847 +        n = nob;
2848 +        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
2849 +                return 1;
2850 +
2851 +        n = nob;
2852 +        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
2853 +                return 1;
2854 +        
2855 +        return 0;
2856 +}
2857 +
2858 +static struct netstrfns *
2859 +libcfs_lnd2netstrfns(int lnd)
2860 +{
2861 +        int    i;
2862 +
2863 +        if (lnd >= 0)
2864 +                for (i = 0; i < libcfs_nnetstrfns; i++)
2865 +                        if (lnd == libcfs_netstrfns[i].nf_type)
2866 +                                return &libcfs_netstrfns[i];
2867 +
2868 +        return NULL;
2869 +}
2870 +
2871 +static struct netstrfns *
2872 +libcfs_str2net_internal(char *str, uint32_t *net)
2873 +{
2874 +        struct netstrfns *nf;
2875 +        int               nob;
2876 +        int               netnum;
2877 +        int               i;
2878 +
2879 +        for (i = 0; i < libcfs_nnetstrfns; i++) {
2880 +                nf = &libcfs_netstrfns[i];
2881 +                if (nf->nf_type >= 0 &&
2882 +                    !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
2883 +                        break;
2884 +        }
2885 +
2886 +        if (i == libcfs_nnetstrfns)
2887 +                return NULL;
2888 +
2889 +        nob = strlen(nf->nf_name);
2890 +
2891 +        if (strlen(str) == (unsigned int)nob) {
2892 +                netnum = 0;
2893 +        } else {
2894 +                if (nf->nf_type == LOLND) /* net number not allowed */
2895 +                        return NULL;
2896 +
2897 +                str += nob;
2898 +                i = strlen(str);
2899 +                if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
2900 +                    i != (int)strlen(str))
2901 +                        return NULL;
2902 +        }
2903 +
2904 +        *net = LNET_MKNET(nf->nf_type, netnum);
2905 +        return nf;
2906 +}
2907 +
2908 +lnet_nid_t
2909 +libcfs_str2nid(char *str)
2910 +{
2911 +        char             *sep = strchr(str, '@');
2912 +        struct netstrfns *nf;
2913 +        uint32_t             net;
2914 +        uint32_t             addr;
2915 +
2916 +        if (sep != NULL) {
2917 +                nf = libcfs_str2net_internal(sep + 1, &net);
2918 +                if (nf == NULL)
2919 +                        return LNET_NID_ANY;
2920 +        } else {
2921 +                sep = str + strlen(str);
2922 +                net = LNET_MKNET(SOCKLND, 0);
2923 +                nf = libcfs_lnd2netstrfns(SOCKLND);
2924 +                if (!nf)
2925 +                        return LNET_NID_ANY;
2926 +        }
2927 +
2928 +        if (!nf->nf_str2addr(str, sep - str, &addr))
2929 +                return LNET_NID_ANY;
2930 +
2931 +        return LNET_MKNID(net, addr);
2932 +}
2933 +
2934 +/****************************************
2935 + * user mapping database handling       *
2936 + * (very rudiment)                      *
2937 + ****************************************/
2938 +
2939 +#define MAPPING_GROW_SIZE       512
2940 +#define MAX_LINE_LEN            1024
2941 +
2942 +struct user_map_item {
2943 +        char        *principal; /* NULL means match all */
2944 +        lnet_nid_t   nid;
2945 +        uid_t        uid;
2946 +};
2947 +
2948 +struct user_mapping {
2949 +        int                   size;
2950 +        int                   nitems;
2951 +        struct user_map_item *items;
2952 +};
2953 +
2954 +static struct user_mapping mapping = {0, 0, NULL};
2955 +/* FIXME to be finished: monitor change of mapping database */
2956 +static int mapping_mtime = 0;
2957 +
2958 +static
2959 +void cleanup_mapping(void)
2960 +{
2961 +        int n;
2962 +
2963 +        for (n = 0; n < mapping.nitems; n++) {
2964 +                if (mapping.items[n].principal)
2965 +                        free(mapping.items[n].principal);
2966 +        }
2967 +        mapping.nitems = 0;
2968 +}
2969 +
2970 +static
2971 +int grow_mapping(int size)
2972 +{
2973 +        struct user_map_item *new;
2974 +        int newsize;
2975 +
2976 +        if (size <= mapping.size)
2977 +                return 0;
2978 +
2979 +        newsize = mapping.size + MAPPING_GROW_SIZE;
2980 +        while (newsize < size)
2981 +                newsize += MAPPING_GROW_SIZE;
2982 +
2983 +        new = malloc(newsize * sizeof(struct user_map_item));
2984 +        if (!new) {
2985 +                printerr(0, "can't alloc mapping size %d\n", newsize);
2986 +                return -1;
2987 +        }
2988 +        memcpy(new, mapping.items, mapping.nitems * sizeof(void*));
2989 +        free(mapping.items);
2990 +        mapping.items = new;
2991 +        mapping.size = newsize;
2992 +        return 0;
2993 +}
2994 +
2995 +uid_t parse_uid(char *uidstr)
2996 +{
2997 +        struct passwd *pw;
2998 +        char *p = NULL;
2999 +        long uid;
3000 +
3001 +        pw = getpwnam(uidstr);
3002 +        if (pw)
3003 +                return pw->pw_uid;
3004 +
3005 +        uid = strtol(uidstr, &p, 0);
3006 +        if (*p == '\0')
3007 +                return (uid_t) uid;
3008 +
3009 +        return -1;
3010 +}
3011 +
3012 +static
3013 +int read_mapping_db(void)
3014 +{
3015 +        char princ[MAX_LINE_LEN];
3016 +        char nid_str[MAX_LINE_LEN];
3017 +        char dest[MAX_LINE_LEN];
3018 +        lnet_nid_t nid;
3019 +        uid_t dest_uid;
3020 +        FILE *f;
3021 +        char *line, linebuf[MAX_LINE_LEN];
3022 +
3023 +        /* cleanup old mappings */
3024 +        cleanup_mapping();
3025 +
3026 +        f = fopen(MAPPING_DATABASE_FILE, "r");
3027 +        if (!f) {
3028 +                printerr(0, "can't open mapping database: %s\n",
3029 +                         MAPPING_DATABASE_FILE);
3030 +                return -1;
3031 +        }
3032 +
3033 +        while ((line = fgets(linebuf, MAX_LINE_LEN, f))) {
3034 +                char *name;
3035 +
3036 +                if (strlen(line) >= MAX_LINE_LEN) {
3037 +                        printerr(0, "invalid mapping db: line too long (%d)\n",
3038 +                                 strlen(line));
3039 +                        cleanup_mapping();
3040 +                        fclose(f);
3041 +                        return -1;
3042 +                }
3043 +                if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
3044 +                        printerr(0, "mapping db: syntax error\n");
3045 +                        cleanup_mapping();
3046 +                        fclose(f);
3047 +                        return -1;
3048 +                }
3049 +                if (grow_mapping(mapping.nitems + 1)) {
3050 +                        printerr(0, "fail to grow mapping to %d\n",
3051 +                                 mapping.nitems + 1);
3052 +                        fclose(f);
3053 +                        return -1;
3054 +                }
3055 +                if (!strcmp(princ, "*")) {
3056 +                        name = NULL;
3057 +                } else {
3058 +                        name = strdup(princ);
3059 +                        if (!name) {
3060 +                                printerr(0, "fail to dup str %s\n", princ);
3061 +                                fclose(f);
3062 +                                return -1;
3063 +                        }
3064 +                }
3065 +                if (!strcmp(nid_str, "*")) {
3066 +                        nid = LNET_NID_ANY;
3067 +                } else {
3068 +                        nid = libcfs_str2nid(nid_str);
3069 +                        if (nid == LNET_NID_ANY) {
3070 +                                printerr(0, "fail to parse nid %s\n", nid_str);
3071 +                                fclose(f);
3072 +                                return -1;
3073 +                        }
3074 +                }
3075 +                dest_uid = parse_uid(dest);
3076 +                if (dest_uid == -1) {
3077 +                        printerr(0, "no valid user: %s\n", dest);
3078 +                        free(name);
3079 +                        fclose(f);
3080 +                        return -1;
3081 +                }
3082 +
3083 +                mapping.items[mapping.nitems].principal = name;
3084 +                mapping.items[mapping.nitems].nid = nid;
3085 +                mapping.items[mapping.nitems].uid = dest_uid;
3086 +                mapping.nitems++;
3087 +                printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
3088 +                         name ? name : "*", nid_str, nid, dest_uid);
3089 +        }
3090 +
3091 +        return 0;
3092 +}
3093 +
3094 +static inline int mapping_changed(void)
3095 +{
3096 +        struct stat st;
3097 +
3098 +        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
3099 +                /* stat failed, treat it like doesn't exist or be removed */
3100 +                if (mapping_mtime == 0) {
3101 +                        return 0;
3102 +                } else {
3103 +                        printerr(0, "Warning: stat %s failed: %s\n",
3104 +                                 MAPPING_DATABASE_FILE, strerror(errno));
3105 +
3106 +                        mapping_mtime = 0;
3107 +                        return 1;
3108 +                }
3109 +        }
3110 +
3111 +        if (st.st_mtime != mapping_mtime) {
3112 +                mapping_mtime = st.st_mtime;
3113 +                return 1;
3114 +        }
3115 +
3116 +        return 0;
3117 +}
3118 +
3119 +int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
3120 +{
3121 +        int n;
3122 +
3123 +        /* FIXME race condition here */
3124 +        if (mapping_changed()) {
3125 +                if (read_mapping_db())
3126 +                        printerr(0, "all remote users will be denied\n");
3127 +        }
3128 +
3129 +        for (n = 0; n < mapping.nitems; n++) {
3130 +                struct user_map_item *entry = &mapping.items[n];
3131 +
3132 +                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
3133 +                        continue;
3134 +                if (!entry->principal ||
3135 +                    !strcasecmp(entry->principal, princ)) {
3136 +                        printerr(1, "found mapping: %s ==> %d\n",
3137 +                                 princ, entry->uid);
3138 +                        *uid = entry->uid;
3139 +                        return 0;
3140 +                }
3141 +        }
3142 +        printerr(2, "no mapping for %s/%#Lx\n", princ, nid);
3143 +        *uid = -1;
3144 +        return -1;
3145 +}
3146 +
3147 diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.h nfs-utils-1.0.10/utils/gssd/lsupport.h
3148 --- nfs-utils-1.0.10.orig/utils/gssd/lsupport.h 2006-11-15 21:41:23.000000000 -0700
3149 +++ nfs-utils-1.0.10/utils/gssd/lsupport.h      2006-12-15 15:12:23.000000000 -0700
3150 @@ -0,0 +1,89 @@
3151 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
3152 + * vim:expandtab:shiftwidth=8:tabstop=8:
3153 + */
3154 +
3155 +#ifndef __LIBCFS_H__
3156 +#define __LIBCFS_H__
3157 +
3158 +#include <unistd.h>
3159 +#include <stdint.h>
3160 +
3161 +#define GSSD_CLI        (0)
3162 +#define GSSD_SVC        (1)
3163 +
3164 +void gssd_init_unique(int type);
3165 +void gssd_exit_unique(int type);
3166 +
3167 +/*
3168 + * copied from lustre source
3169 + */
3170 +
3171 +#define LUSTRE_GSS_SVC_MDS      0
3172 +#define LUSTRE_GSS_SVC_OSS      1
3173 +
3174 +struct lgssd_upcall_data {
3175 +        uint32_t        seq;
3176 +        uint32_t        uid;
3177 +        uint32_t        gid;
3178 +        uint32_t        svc;
3179 +        uint64_t        nid;
3180 +        uint64_t        pag;
3181 +        char            obd[64];
3182 +};
3183 +
3184 +#define GSSD_INTERFACE_VERSION        (1)
3185 +
3186 +struct lgssd_ioctl_param {
3187 +        int             version;        /* in   */
3188 +        char           *uuid;           /* in   */
3189 +        int             lustre_svc;     /* in   */
3190 +        uid_t           uid;            /* in   */
3191 +        gid_t           gid;            /* in   */
3192 +        long            send_token_size;/* in   */
3193 +        char           *send_token;     /* in   */
3194 +        long            reply_buf_size; /* in   */
3195 +        char           *reply_buf;      /* in   */
3196 +        long            status;         /* out  */
3197 +        long            reply_length;   /* out  */
3198 +};
3199 +
3200 +#define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
3201 +#define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
3202 +
3203 +typedef uint64_t lnet_nid_t;
3204 +typedef uint32_t lnet_netid_t;
3205 +
3206 +#define LNET_NID_ANY      ((lnet_nid_t) -1)
3207 +#define LNET_PID_ANY      ((lnet_pid_t) -1)
3208 +
3209 +enum {
3210 +        /* Only add to these values (i.e. don't ever change or redefine them):
3211 +         * network addresses depend on them... */
3212 +        QSWLND    = 1,
3213 +        SOCKLND   = 2,
3214 +        GMLND     = 3,
3215 +        PTLLND    = 4,
3216 +        O2IBLND   = 5,
3217 +        CIBLND    = 6,
3218 +        OPENIBLND = 7,
3219 +        IIBLND    = 8,
3220 +        LOLND     = 9,
3221 +        RALND     = 10,
3222 +        VIBLND    = 11,
3223 +        LND_ENUM_END_MARKER
3224 +};
3225 +
3226 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
3227 +int lookup_mapping(char *princ, uint64_t nid, uid_t *uid);
3228 +lnet_nid_t libcfs_str2nid(char *str);
3229 +
3230 +/* how an LNET NID encodes net:address */
3231 +#define LNET_NIDADDR(nid)      ((uint32_t)((nid) & 0xffffffff))
3232 +#define LNET_NIDNET(nid)       ((uint32_t)(((nid) >> 32)) & 0xffffffff)
3233 +#define LNET_MKNID(net,addr)   ((((uint64_t)(net))<<32)|((uint64_t)(addr)))
3234 +/* how net encodes type:number */
3235 +#define LNET_NETNUM(net)       ((net) & 0xffff)
3236 +#define LNET_NETTYP(net)       (((net) >> 16) & 0xffff)
3237 +#define LNET_MKNET(typ,num)    ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
3238 +
3239 +#endif /* __LIBCFS_H__ */
3240 diff -rup nfs-utils-1.0.10.orig/utils/gssd/Makefile.am nfs-utils-1.0.10/utils/gssd/Makefile.am
3241 --- nfs-utils-1.0.10.orig/utils/gssd/Makefile.am        2006-11-15 21:26:08.000000000 -0700
3242 +++ nfs-utils-1.0.10/utils/gssd/Makefile.am     2006-12-15 15:11:52.000000000 -0700
3243 @@ -1,17 +1,11 @@
3244  ## Process this file with automake to produce Makefile.in
3245  
3246 -man8_MANS      = gssd.man svcgssd.man
3247 -
3248 -RPCPREFIX      = rpc.
3249 +RPCPREFIX      = 
3250  KPREFIX                = @kprefix@
3251 -sbin_PREFIXED  = gssd svcgssd
3252 -sbin_PROGRAMS  = $(sbin_PREFIXED) gss_clnt_send_err
3253 +sbin_PREFIXED  = lgssd lsvcgssd
3254 +sbin_PROGRAMS  = $(sbin_PREFIXED)
3255  sbin_SCRIPTS   = gss_destroy_creds
3256  
3257 -EXTRA_DIST = \
3258 -       gss_destroy_creds \
3259 -       $(man8_MANS)
3260 -
3261  COMMON_SRCS = \
3262         context.c \
3263         context_mit.c \
3264 @@ -21,13 +15,15 @@ COMMON_SRCS = \
3265         gss_util.c \
3266         gss_oids.c \
3267         err_util.c \
3268 +       lsupport.c \
3269         \
3270         context.h \
3271         err_util.h \
3272         gss_oids.h \
3273 -       gss_util.h
3274 +       gss_util.h \
3275 +       lsupport.h
3276  
3277 -gssd_SOURCES = \
3278 +lgssd_SOURCES = \
3279         $(COMMON_SRCS) \
3280         gssd.c \
3281         gssd_main_loop.c \
3282 @@ -38,13 +34,12 @@ gssd_SOURCES = \
3283         krb5_util.h \
3284         write_bytes.h
3285  
3286 -gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
3287 -gssd_LDFLAGS = $(KRBLDFLAGS)
3288 +lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
3289 +lgssd_LDFLAGS = $(KRBLDFLAGS)
3290  
3291 -gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
3292 -             $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
3293 +lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
3294  
3295 -svcgssd_SOURCES = \
3296 +lsvcgssd_SOURCES = \
3297         $(COMMON_SRCS) \
3298         cacheio.c \
3299         svcgssd.c \
3300 @@ -55,20 +50,11 @@ svcgssd_SOURCES = \
3301         cacheio.h \
3302         svcgssd.h
3303  
3304 -svcgssd_LDADD = \
3305 -       ../../support/nfs/libnfs.a \
3306 -       $(RPCSECGSS_LIBS) -lnfsidmap \
3307 -       $(KRBLIBS)
3308 -
3309 -svcgssd_LDFLAGS = $(KRBLDFLAGS)
3310 -
3311 -svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
3312 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
3313 +lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
3314  
3315 -gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
3316 +lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
3317  
3318 -gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
3319 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
3320 +lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
3321  
3322  MAINTAINERCLEANFILES = Makefile.in
3323  
3324 @@ -92,23 +78,3 @@ uninstall-hook:
3325           done)
3326  
3327  
3328 -# XXX This makes some assumptions about what automake does.
3329 -# XXX But there is no install-man-hook or install-man-local.
3330 -install-man: install-man8 install-man-links
3331 -uninstall-man: uninstall-man8 uninstall-man-links
3332 -
3333 -install-man-links:
3334 -       (cd $(DESTDIR)$(man8dir) && \
3335 -         for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
3336 -           inst=`echo $$m | sed -e 's/man$$/8/'`; \
3337 -           rm -f $(RPCPREFIX)$$inst ; \
3338 -           $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
3339 -         done)
3340 -
3341 -uninstall-man-links:
3342 -       (cd $(DESTDIR)$(man8dir) && \
3343 -         for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
3344 -           inst=`echo $$m | sed -e 's/man$$/8/'`; \
3345 -           rm -f $(RPCPREFIX)$$inst ; \
3346 -         done)
3347 -
3348 diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c nfs-utils-1.0.10/utils/gssd/svcgssd.c
3349 --- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c  2006-08-07 00:40:50.000000000 -0600
3350 +++ nfs-utils-1.0.10/utils/gssd/svcgssd.c       2006-12-15 15:12:23.000000000 -0700
3351 @@ -43,7 +43,6 @@
3352  #include <sys/types.h>
3353  #include <sys/stat.h>
3354  #include <sys/socket.h>
3355 -#include <rpc/rpc.h>
3356  #include <fcntl.h>
3357  #include <errno.h>
3358  
3359 @@ -54,11 +53,33 @@
3360  #include <stdlib.h>
3361  #include <string.h>
3362  #include <signal.h>
3363 -#include "nfslib.h"
3364 +#include <dirent.h>
3365  #include "svcgssd.h"
3366  #include "gss_util.h"
3367  #include "err_util.h"
3368 +#include "lsupport.h"
3369  
3370 +void
3371 +closeall(int min)
3372 +{
3373 +       DIR *dir = opendir("/proc/self/fd");
3374 +       if (dir != NULL) {
3375 +               int dfd = dirfd(dir);
3376 +               struct dirent *d;
3377 +
3378 +               while ((d = readdir(dir)) != NULL) {
3379 +                       char *endp;
3380 +                       long n = strtol(d->d_name, &endp, 10);
3381 +                       if (*endp != '\0' && n >= min && n != dfd)
3382 +                               (void) close(n);
3383 +               }
3384 +               closedir(dir);
3385 +       } else {
3386 +               int fd = sysconf(_SC_OPEN_MAX);
3387 +               while (--fd >= min)
3388 +                       (void) close(fd);
3389 +       }
3390 +}
3391  /*
3392   * mydaemon creates a pipe between the partent and child
3393   * process. The parent process will wait until the
3394 @@ -165,8 +186,8 @@ main(int argc, char *argv[])
3395         int get_creds = 1;
3396         int fg = 0;
3397         int verbosity = 0;
3398 -       int rpc_verbosity = 0;
3399         int opt;
3400 +       int must_srv_mds = 0, must_srv_oss = 0;
3401         extern char *optarg;
3402         char *progname;
3403  
3404 @@ -181,8 +202,13 @@ main(int argc, char *argv[])
3405                         case 'v':
3406                                 verbosity++;
3407                                 break;
3408 -                       case 'r':
3409 -                               rpc_verbosity++;
3410 +                       case 'm':
3411 +                               get_creds = 1;
3412 +                               must_srv_mds = 1;
3413 +                               break;
3414 +                       case 'o':
3415 +                               get_creds = 1;
3416 +                               must_srv_oss = 1;
3417                                 break;
3418                         default:
3419                                 usage(argv[0]);
3420 @@ -196,27 +222,18 @@ main(int argc, char *argv[])
3421                 progname = argv[0];
3422  
3423         initerr(progname, verbosity, fg);
3424 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
3425 -       authgss_set_debug_level(rpc_verbosity);
3426 -#else
3427 -       if (rpc_verbosity > 0)
3428 -               printerr(0, "Warning: rpcsec_gss library does not "
3429 -                           "support setting debug level\n");
3430 -#endif
3431  
3432         if (gssd_check_mechs() != 0) {
3433                 printerr(0, "ERROR: Problem with gssapi library\n");
3434                 exit(1);
3435         }
3436  
3437 -       if (!fg)
3438 -               mydaemon(0, 0);
3439 -
3440 -       signal(SIGINT, sig_die);
3441 -       signal(SIGTERM, sig_die);
3442 -       signal(SIGHUP, sig_hup);
3443 +       if (gssd_get_local_realm()) {
3444 +               printerr(0, "ERROR: Can't get Local Kerberos realm\n");
3445 +               exit(1);
3446 +       }
3447  
3448 -       if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
3449 +       if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
3450                  printerr(0, "unable to obtain root (machine) credentials\n");
3451                  printerr(0, "do you have a keytab entry for "
3452                             "nfs/<your.host>@<YOUR.REALM> in "
3453 @@ -225,9 +242,18 @@ main(int argc, char *argv[])
3454         }
3455  
3456         if (!fg)
3457 +               mydaemon(0, 0);
3458 +
3459 +       signal(SIGINT, sig_die);
3460 +       signal(SIGTERM, sig_die);
3461 +       signal(SIGHUP, sig_hup);
3462 +
3463 +       if (!fg)
3464                 release_parent();
3465  
3466 -       gssd_run();
3467 +       gssd_init_unique(GSSD_SVC);
3468 +
3469 +       svcgssd_run();
3470         printerr(0, "gssd_run returned!\n");
3471         abort();
3472  }
3473 diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h nfs-utils-1.0.10/utils/gssd/svcgssd.h
3474 --- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h  2006-08-07 00:40:50.000000000 -0600
3475 +++ nfs-utils-1.0.10/utils/gssd/svcgssd.h       2006-12-15 15:12:23.000000000 -0700
3476 @@ -35,9 +35,20 @@
3477  #include <sys/queue.h>
3478  #include <gssapi/gssapi.h>
3479  
3480 -void handle_nullreq(FILE *f);
3481 -void gssd_run(void);
3482 +int handle_nullreq(FILE *f);
3483 +void svcgssd_run(void);
3484 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
3485 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
3486  
3487 -#define GSSD_SERVICE_NAME      "nfs"
3488 +extern char *mds_local_realm;
3489 +extern char *oss_local_realm;
3490 +
3491 +#define GSSD_SERVICE_NAME      "lustre"
3492 +
3493 +/* XXX */
3494 +#define GSSD_SERVICE_MDS                       "lustre_mds"
3495 +#define GSSD_SERVICE_OSS                       "lustre_oss"
3496 +#define LUSTRE_ROOT_NAME                       "lustre_root"
3497 +#define LUSTRE_ROOT_NAMELEN                    11
3498  
3499  #endif /* _RPC_SVCGSSD_H_ */
3500 diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c
3501 --- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c        2006-08-07 00:40:50.000000000 -0600
3502 +++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c     2006-12-15 15:12:23.000000000 -0700
3503 @@ -46,46 +46,66 @@
3504  #include "svcgssd.h"
3505  #include "err_util.h"
3506  
3507 +/*
3508 + * nfs4 in-kernel cache implementation make upcall failed directly
3509 + * if there's no listener detected. so here we should keep the init
3510 + * channel file open as possible as we can.
3511 + *
3512 + * unfortunately the proc doesn't support dir change notification.
3513 + * and when an entry get unlinked, we only got POLLIN event once,
3514 + * it's the only oppotunity we can close the file and startover.
3515 + */
3516  void
3517 -gssd_run()
3518 +svcgssd_run()
3519  {
3520         int                     ret;
3521 -       FILE                    *f;
3522 +       FILE                    *f = NULL;
3523         struct pollfd           pollfd;
3524 +       struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
3525  
3526 -#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
3527 +#define NULLRPC_FILE "/proc/net/rpc/auth.ptlrpcs.init/channel"
3528  
3529 -       f = fopen(NULLRPC_FILE, "rw");
3530 -
3531 -       if (!f) {
3532 -               printerr(0, "failed to open %s: %s\n",
3533 -                        NULLRPC_FILE, strerror(errno));
3534 -               exit(1);
3535 -       }
3536 -       pollfd.fd = fileno(f);
3537 -       pollfd.events = POLLIN;
3538         while (1) {
3539                 int save_err;
3540  
3541 +               while (f == NULL) {
3542 +                       f = fopen(NULLRPC_FILE, "rw");
3543 +                       if (f == NULL) {
3544 +                               printerr(4, "failed to open %s: %s\n",
3545 +                                        NULLRPC_FILE, strerror(errno));
3546 +                               nanosleep(&halfsec, NULL);
3547 +                       } else {
3548 +                               printerr(1, "successfully open %s\n",
3549 +                                        NULLRPC_FILE);
3550 +                               break;
3551 +                       }
3552 +               }
3553 +               pollfd.fd = fileno(f);
3554 +               pollfd.events = POLLIN;
3555 +
3556                 pollfd.revents = 0;
3557 -               printerr(1, "entering poll\n");
3558 -               ret = poll(&pollfd, 1, -1);
3559 +               ret = poll(&pollfd, 1, 1000);
3560                 save_err = errno;
3561 -               printerr(1, "leaving poll\n");
3562 +
3563                 if (ret < 0) {
3564 -                       if (save_err != EINTR)
3565 -                               printerr(0, "error return from poll: %s\n",
3566 -                                        strerror(save_err));
3567 +                       printerr(0, "error return from poll: %s\n",
3568 +                                strerror(save_err));
3569 +                       fclose(f);
3570 +                       f = NULL;
3571                 } else if (ret == 0) {
3572 -                       /* timeout; shouldn't happen. */
3573 +                       printerr(3, "poll timeout\n");
3574                 } else {
3575                         if (ret != 1) {
3576                                 printerr(0, "bug: unexpected poll return %d\n",
3577                                                 ret);
3578                                 exit(1);
3579                         }
3580 -                       if (pollfd.revents & POLLIN)
3581 -                               handle_nullreq(f);
3582 +                       if (pollfd.revents & POLLIN) {
3583 +                               if (handle_nullreq(f) < 0) {
3584 +                                       fclose(f);
3585 +                                       f = NULL;
3586 +                               }
3587 +                       }
3588                 }
3589         }
3590  }
3591 diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c
3592 --- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c     2006-08-07 00:40:50.000000000 -0600
3593 +++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c  2006-12-15 15:12:23.000000000 -0700
3594 @@ -35,7 +35,6 @@
3595  
3596  #include <sys/param.h>
3597  #include <sys/stat.h>
3598 -#include <rpc/rpc.h>
3599  
3600  #include <pwd.h>
3601  #include <stdio.h>
3602 @@ -44,25 +43,28 @@
3603  #include <string.h>
3604  #include <fcntl.h>
3605  #include <errno.h>
3606 -#include <nfsidmap.h>
3607 +#include <netdb.h>
3608  
3609  #include "svcgssd.h"
3610  #include "gss_util.h"
3611  #include "err_util.h"
3612  #include "context.h"
3613  #include "cacheio.h"
3614 +#include "lsupport.h"
3615  
3616  extern char * mech2file(gss_OID mech);
3617 -#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
3618 -#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.rpcsec.init/channel"
3619 +#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel"
3620 +#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.ptlrpcs.init/channel"
3621  
3622  #define TOKEN_BUF_SIZE         8192
3623  
3624  struct svc_cred {
3625 -       uid_t   cr_uid;
3626 -       gid_t   cr_gid;
3627 -       int     cr_ngroups;
3628 -       gid_t   cr_groups[NGROUPS];
3629 +       uint32_t cr_remote;
3630 +       uint32_t cr_usr_root;
3631 +       uint32_t cr_usr_mds;
3632 +       uid_t    cr_uid;
3633 +       uid_t    cr_mapped_uid;
3634 +       uid_t    cr_gid;
3635  };
3636  
3637  static int
3638 @@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han
3639                 gss_OID mech, gss_buffer_desc *context_token)
3640  {
3641         FILE *f;
3642 -       int i;
3643         char *fname = NULL;
3644  
3645 -       printerr(1, "doing downcall\n");
3646 +       printerr(2, "doing downcall\n");
3647         if ((fname = mech2file(mech)) == NULL)
3648                 goto out_err;
3649         f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
3650 @@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han
3651         qword_printhex(f, out_handle->value, out_handle->length);
3652         /* XXX are types OK for the rest of this? */
3653         qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
3654 +       qword_printint(f, cred->cr_remote);
3655 +       qword_printint(f, cred->cr_usr_root);
3656 +       qword_printint(f, cred->cr_usr_mds);
3657 +       qword_printint(f, cred->cr_mapped_uid);
3658         qword_printint(f, cred->cr_uid);
3659         qword_printint(f, cred->cr_gid);
3660 -       qword_printint(f, cred->cr_ngroups);
3661 -       for (i=0; i < cred->cr_ngroups; i++)
3662 -               qword_printint(f, cred->cr_groups[i]);
3663         qword_print(f, fname);
3664         qword_printhex(f, context_token->value, context_token->length);
3665         qword_eol(f);
3666 @@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc *
3667         /* XXXARG: */
3668         int g;
3669  
3670 -       printerr(1, "sending null reply\n");
3671 +       printerr(2, "sending null reply\n");
3672  
3673         qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
3674         qword_addhex(&bp, &blen, in_token->value, in_token->length);
3675 @@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc *
3676  #define rpcsec_gsserr_credproblem      13
3677  #define rpcsec_gsserr_ctxproblem       14
3678  
3679 +#if 0
3680  static void
3681  add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
3682  {
3683 @@ -182,7 +185,9 @@ add_supplementary_groups(char *secname, 
3684                 }
3685         }
3686  }
3687 +#endif
3688  
3689 +#if 0
3690  static int
3691  get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
3692  {
3693 @@ -248,7 +253,9 @@ out_free:
3694  out:
3695         return res;
3696  }
3697 +#endif
3698  
3699 +#if 0
3700  void
3701  print_hexl(int pri, unsigned char *cp, int length)
3702  {
3703 @@ -285,12 +292,121 @@ print_hexl(int pri, unsigned char *cp, i
3704                 printerr(pri,"\n");
3705         }
3706  }
3707 +#endif
3708  
3709 -void
3710 +static int
3711 +get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
3712 +       lnet_nid_t nid, uint32_t lustre_svc)
3713 +{
3714 +       u_int32_t       maj_stat, min_stat;
3715 +       gss_buffer_desc name;
3716 +       char            *sname, *realm, *slash;
3717 +       int             res = -1;
3718 +       gss_OID         name_type = GSS_C_NO_OID;
3719 +       struct passwd   *pw;
3720 +
3721 +       cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
3722 +       cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
3723 +
3724 +       maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
3725 +       if (maj_stat != GSS_S_COMPLETE) {
3726 +               pgsserr("get_ids: gss_display_name",
3727 +                       maj_stat, min_stat, mech);
3728 +               return -1;
3729 +       }
3730 +       if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
3731 +           !(sname = calloc(name.length + 1, 1))) {
3732 +               printerr(0, "WARNING: get_ids: error allocating %d bytes "
3733 +                       "for sname\n", name.length + 1);
3734 +               gss_release_buffer(&min_stat, &name);
3735 +               return -1;
3736 +       }
3737 +       memcpy(sname, name.value, name.length);
3738 +       printerr(1, "authenticated %s from %016llx\n", sname, nid);
3739 +       gss_release_buffer(&min_stat, &name);
3740 +
3741 +       if (lustre_svc == LUSTRE_GSS_SVC_MDS)
3742 +               lookup_mapping(sname, nid, &cred->cr_mapped_uid);
3743 +       else
3744 +               cred->cr_mapped_uid = -1;
3745 +
3746 +        realm = strchr(sname, '@');
3747 +        if (!realm) {
3748 +                printerr(0, "WARNNING: principal %s contains no realm name\n",
3749 +                        sname);
3750 +                cred->cr_remote = (mds_local_realm != NULL);
3751 +        } else {
3752 +                *realm++ = '\0';
3753 +                if (!mds_local_realm)
3754 +                        cred->cr_remote = 1;
3755 +                else
3756 +                        cred->cr_remote =
3757 +                                (strcasecmp(mds_local_realm, realm) != 0);
3758 +        }
3759 +
3760 +        if (cred->cr_remote) {
3761 +                if (cred->cr_mapped_uid != -1)
3762 +                        res = 0;
3763 +               else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
3764 +                        strcmp(sname, "lustre_root") == 0)
3765 +                        res = 0;
3766 +                else
3767 +                        printerr(0, "principal %s is remote without mapping\n",
3768 +                                 sname);
3769 +               goto out_free;
3770 +        }
3771 +
3772 +        slash = strchr(sname, '/');
3773 +        if (slash)
3774 +                *slash = '\0';
3775 +
3776 +        if (!(pw = getpwnam(sname))) {
3777 +                /* If client use machine credential, we map it to root, which
3778 +                 * will subject to further mapping by root-squash in kernel.
3779 +                 *
3780 +                 * MDS service keytab is treated as special user, also mapped
3781 +                 * to root. OSS service keytab can't be used as a user.
3782 +                 */
3783 +                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
3784 +                        printerr(2, "lustre_root principal, resolve to uid 0\n");
3785 +                        cred->cr_uid = 0;
3786 +                        cred->cr_usr_root = 1;
3787 +                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
3788 +                        printerr(2, "mds service principal, resolve to uid 0\n");
3789 +                        cred->cr_uid = 0;
3790 +                        cred->cr_usr_mds = 1;
3791 +                } else {
3792 +                        cred->cr_uid = -1;
3793 +                        if (cred->cr_mapped_uid == -1) {
3794 +                                printerr(0, "invalid user %s\n", sname);
3795 +                                goto out_free;
3796 +                        }
3797 +                        printerr(2, "user %s mapped to %u\n",
3798 +                                 sname, cred->cr_mapped_uid);
3799 +                }
3800 +        } else {
3801 +                cred->cr_uid = pw->pw_uid;
3802 +                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
3803 +        }
3804 +
3805 +        res = 0;
3806 +out_free:
3807 +        free(sname);
3808 +        return res;
3809 +}
3810 +
3811 +typedef struct gss_union_ctx_id_t {
3812 +       gss_OID         mech_type;
3813 +       gss_ctx_id_t    internal_ctx_id;
3814 +} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
3815 +
3816 +/*
3817 + * return -1 only if we detect error during reading from upcall channel,
3818 + * all other cases return 0.
3819 + */
3820 +int
3821  handle_nullreq(FILE *f) {
3822 -       /* XXX initialize to a random integer to reduce chances of unnecessary
3823 -        * invalidation of existing ctx's on restarting svcgssd. */
3824 -       static u_int32_t        handle_seq = 0;
3825 +       uint64_t                handle_seq;
3826         char                    in_tok_buf[TOKEN_BUF_SIZE];
3827         char                    in_handle_buf[15];
3828         char                    out_handle_buf[15];
3829 @@ -302,10 +418,13 @@ handle_nullreq(FILE *f) {
3830                                 ignore_out_tok = {.value = NULL},
3831         /* XXX isn't there a define for this?: */
3832                                 null_token = {.value = NULL};
3833 +       uint32_t                lustre_svc;
3834 +       lnet_nid_t              nid;
3835         u_int32_t               ret_flags;
3836         gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
3837         gss_name_t              client_name;
3838         gss_OID                 mech = GSS_C_NO_OID;
3839 +       gss_cred_id_t           svc_cred;
3840         u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
3841         u_int32_t               ignore_min_stat;
3842         struct svc_cred         cred;
3843 @@ -313,25 +432,31 @@ handle_nullreq(FILE *f) {
3844         static int              lbuflen = 0;
3845         static char             *cp;
3846  
3847 -       printerr(1, "handling null request\n");
3848 +       printerr(2, "handling null request\n");
3849  
3850         if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
3851                 printerr(0, "WARNING: handle_nullreq: "
3852                             "failed reading request\n");
3853 -               return;
3854 +               return -1;
3855         }
3856  
3857         cp = lbuf;
3858  
3859 +       qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
3860 +       qword_get(&cp, (char *) &nid, sizeof(nid));
3861 +       qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
3862 +       printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
3863 +                lustre_svc, nid, handle_seq);
3864 +
3865         in_handle.length = (size_t) qword_get(&cp, in_handle.value,
3866                                               sizeof(in_handle_buf));
3867 -       printerr(2, "in_handle: \n");
3868 -       print_hexl(2, in_handle.value, in_handle.length);
3869 +       printerr(3, "in_handle: \n");
3870 +       print_hexl(3, in_handle.value, in_handle.length);
3871  
3872         in_tok.length = (size_t) qword_get(&cp, in_tok.value,
3873                                            sizeof(in_tok_buf));
3874 -       printerr(2, "in_tok: \n");
3875 -       print_hexl(2, in_tok.value, in_tok.length);
3876 +       printerr(3, "in_tok: \n");
3877 +       print_hexl(3, in_tok.value, in_tok.length);
3878  
3879         if (in_tok.length < 0) {
3880                 printerr(0, "WARNING: handle_nullreq: "
3881 @@ -351,7 +476,13 @@ handle_nullreq(FILE *f) {
3882                 memcpy(&ctx, in_handle.value, in_handle.length);
3883         }
3884  
3885 -       maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
3886 +       svc_cred = gssd_select_svc_cred(lustre_svc);
3887 +       if (!svc_cred) {
3888 +               printerr(0, "no service credential for svc %u\n", lustre_svc);
3889 +               goto out_err;
3890 +       }
3891 +
3892 +       maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
3893                         &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
3894                         &mech, &out_tok, &ret_flags, NULL, NULL);
3895  
3896 @@ -369,7 +500,8 @@ handle_nullreq(FILE *f) {
3897                         maj_stat, min_stat, mech);
3898                 goto out_err;
3899         }
3900 -       if (get_ids(client_name, mech, &cred)) {
3901 +
3902 +       if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
3903                 /* get_ids() prints error msg */
3904                 maj_stat = GSS_S_BAD_NAME; /* XXX ? */
3905                 gss_release_name(&ignore_min_stat, &client_name);
3906 @@ -377,10 +509,8 @@ handle_nullreq(FILE *f) {
3907         }
3908         gss_release_name(&ignore_min_stat, &client_name);
3909  
3910 -
3911         /* Context complete. Pass handle_seq in out_handle to use
3912          * for context lookup in the kernel. */
3913 -       handle_seq++;
3914         out_handle.length = sizeof(handle_seq);
3915         memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
3916  
3917 @@ -404,8 +534,7 @@ out:
3918                 free(ctx_token.value);
3919         if (out_tok.value != NULL)
3920                 gss_release_buffer(&ignore_min_stat, &out_tok);
3921 -       printerr(1, "finished handling null request\n");
3922 -       return;
3923 +       return 0;
3924  
3925  out_err:
3926         if (ctx != GSS_C_NO_CONTEXT)
3927 diff -rup nfs-utils-1.0.10.orig/utils/Makefile.am nfs-utils-1.0.10/utils/Makefile.am
3928 --- nfs-utils-1.0.10.orig/utils/Makefile.am     2006-08-07 00:40:50.000000000 -0600
3929 +++ nfs-utils-1.0.10/utils/Makefile.am  2006-12-15 15:11:52.000000000 -0700
3930 @@ -2,31 +2,6 @@
3931  
3932  OPTDIRS =
3933  
3934 -if CONFIG_RQUOTAD
3935 -OPTDIRS += rquotad
3936 -endif
3937 -
3938 -if CONFIG_NFSV4
3939 -OPTDIRS += idmapd
3940 -endif
3941 -
3942 -if CONFIG_GSS
3943 -OPTDIRS += gssd
3944 -endif
3945 -
3946 -if CONFIG_MOUNT
3947 -OPTDIRS += mount
3948 -endif
3949 -
3950 -SUBDIRS = \
3951 -       exportfs \
3952 -       lockd \
3953 -       mountd \
3954 -       nfsd \
3955 -       nfsstat \
3956 -       nhfsstone \
3957 -       showmount \
3958 -       statd \
3959 -       $(OPTDIRS)
3960 +SUBDIRS = gssd
3961  
3962  MAINTAINERCLEANFILES = Makefile.in