Whamcloud - gitweb
LU-8769 lnet: removal of obsolete LNDs
[fs/lustre-release.git] / lustre / utils / gss / nfs-utils-1.0.10-lustre.diff
1 diff -rNup nfs-utils-1.0.10/configure.in nfs-utils-1.0.10.lustre/configure.in
2 --- nfs-utils-1.0.10/configure.in       2007-05-15 13:02:26.000000000 -0600
3 +++ nfs-utils-1.0.10.lustre/configure.in        2007-05-15 13:00:53.000000000 -0600
4 @@ -17,61 +17,14 @@ AC_ARG_WITH(release,
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 -rNup nfs-utils-1.0.10/Makefile.am nfs-utils-1.0.10.lustre/Makefile.am
193 --- nfs-utils-1.0.10/Makefile.am        2007-05-15 13:02:26.000000000 -0600
194 +++ nfs-utils-1.0.10.lustre/Makefile.am 2007-05-15 13:00:53.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/cacheio.c nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c
204 --- nfs-utils-1.0.10/utils/gssd/cacheio.c       2006-08-07 00:40:50.000000000 -0600
205 +++ nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c        2007-05-15 13:01:35.000000000 -0600
206 @@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in
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 -rNup nfs-utils-1.0.10/utils/gssd/context.c nfs-utils-1.0.10.lustre/utils/gssd/context.c
217 --- nfs-utils-1.0.10/utils/gssd/context.c       2006-08-07 00:40:50.000000000 -0600
218 +++ nfs-utils-1.0.10.lustre/utils/gssd/context.c        2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/context.h nfs-utils-1.0.10.lustre/utils/gssd/context.h
229 --- nfs-utils-1.0.10/utils/gssd/context.h       2007-05-15 13:02:26.000000000 -0600
230 +++ nfs-utils-1.0.10.lustre/utils/gssd/context.h        2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/context_lucid.c nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c
241 --- nfs-utils-1.0.10/utils/gssd/context_lucid.c 2007-05-15 13:02:26.000000000 -0600
242 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c  2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/context_mit.c nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c
348 --- nfs-utils-1.0.10/utils/gssd/context_mit.c   2007-05-15 13:02:26.000000000 -0600
349 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c    2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/context_spkm3.c nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c
373 --- nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2007-05-15 13:02:26.000000000 -0600
374 +++ nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c  2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/err_util.c nfs-utils-1.0.10.lustre/utils/gssd/err_util.c
385 --- nfs-utils-1.0.10/utils/gssd/err_util.c      2006-08-07 00:40:50.000000000 -0600
386 +++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.c       2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/err_util.h nfs-utils-1.0.10.lustre/utils/gssd/err_util.h
438 --- nfs-utils-1.0.10/utils/gssd/err_util.h      2006-08-07 00:40:50.000000000 -0600
439 +++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.h       2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c
448 --- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c     2006-08-07 00:40:50.000000000 -0600
449 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c      2007-05-15 13:00:53.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/gssd.c nfs-utils-1.0.10.lustre/utils/gssd/gssd.c
464 --- nfs-utils-1.0.10/utils/gssd/gssd.c  2007-05-15 13:02:26.000000000 -0600
465 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.c   2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/gssd.h nfs-utils-1.0.10.lustre/utils/gssd/gssd.h
693 --- nfs-utils-1.0.10/utils/gssd/gssd.h  2007-05-15 13:02:26.000000000 -0600
694 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.h   2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c
751 --- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c        2007-05-15 13:02:26.000000000 -0600
752 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c 2007-05-15 13:01:35.000000000 -0600
753 @@ -94,11 +94,13 @@ scan_poll_results(int ret)
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 -rNup nfs-utils-1.0.10/utils/gssd/gssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c
823 --- nfs-utils-1.0.10/utils/gssd/gssd_proc.c     2007-05-15 13:02:26.000000000 -0600
824 +++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c      2007-05-15 13:21:06.000000000 -0600
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,103 +910,145 @@ 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 +       /* FIXME temporary fix, do this before fork.
1466 +        * in case of errors could have memory leak!!!
1467 +        */
1468 +       if (updata.uid == 0) {
1469 +               if (gssd_get_krb5_machine_cred_list(&credlist)) {
1470 +                       printerr(0, "ERROR: Failed to obtain machine "
1471 +                                   "credentials\n");
1472 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1473 +                       return;
1474 +               }
1475 +       }
1476 +
1477 +       /* fork child process */
1478 +       pid = fork();
1479 +       if (pid < 0) {
1480 +               printerr(0, "can't fork: %s\n", strerror(errno));
1481 +               do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1482 +               return;
1483 +       } else if (pid > 0) {
1484 +               printerr(2, "forked child process: %d\n", pid);
1485 +               return;
1486 +       }
1487 +
1488 +       printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
1489 +                updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
1490 +
1491 +       if (updata.svc != LUSTRE_GSS_SVC_MDS &&
1492 +           updata.svc != LUSTRE_GSS_SVC_OSS) {
1493 +               printerr(0, "invalid svc %d\n", updata.svc);
1494 +               lgd.lgd_rpc_err = -EPROTO;
1495 +               goto out_return_error;
1496 +       }
1497 +       updata.obd[sizeof(updata.obd)-1] = '\0';
1498 +
1499 +       if (construct_service_name(clp, &updata)) {
1500 +               printerr(0, "failed to construct service name\n");
1501 +               goto out_return_error;
1502         }
1503  
1504 -       if (uid == 0) {
1505 +       if (updata.uid == 0) {
1506                 int success = 0;
1507  
1508                 /*
1509                  * Get a list of credential cache names and try each
1510                  * of them until one works or we've tried them all
1511                  */
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 +*/
1523                 for (ccname = credlist; ccname && *ccname; ccname++) {
1524                         gssd_setup_krb5_machine_gss_ccache(*ccname);
1525 -                       if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1526 -                                                   AUTHTYPE_KRB5)) == 0) {
1527 +                       if ((gssd_create_lgd(clp, &lgd, &updata,
1528 +                                            AUTHTYPE_KRB5)) == 0) {
1529                                 /* Success! */
1530                                 success++;
1531                                 break;
1532                         }
1533                         printerr(2, "WARNING: Failed to create krb5 context "
1534                                     "for user with uid %d with credentials "
1535 -                                   "cache %s for server %s\n",
1536 -                                uid, *ccname, clp->servername);
1537 +                                   "cache %s for service %s\n",
1538 +                                updata.uid, *ccname, clp->servicename);
1539                 }
1540                 gssd_free_krb5_machine_cred_list(credlist);
1541                 if (!success) {
1542 -                       printerr(0, "WARNING: Failed to create krb5 context "
1543 +                       printerr(0, "ERROR: Failed to create krb5 context "
1544                                     "for user with uid %d with any "
1545 -                                   "credentials cache for server %s\n",
1546 -                                uid, clp->servername);
1547 +                                   "credentials cache for service %s\n",
1548 +                                updata.uid, clp->servicename);
1549                         goto out_return_error;
1550                 }
1551         }
1552         else {
1553                 /* Tell krb5 gss which credentials cache to use */
1554 -               gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
1555 +               gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
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 -rNup nfs-utils-1.0.10/utils/gssd/gss_util.c nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c
1627 --- nfs-utils-1.0.10/utils/gssd/gss_util.c      2006-08-07 00:40:50.000000000 -0600
1628 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c       2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/gss_util.h nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h
1843 --- nfs-utils-1.0.10/utils/gssd/gss_util.h      2006-08-07 00:40:50.000000000 -0600
1844 +++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h       2007-05-15 13:01:35.000000000 -0600
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 -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.c nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c
1863 --- nfs-utils-1.0.10/utils/gssd/krb5_util.c     2007-05-15 13:02:26.000000000 -0600
1864 +++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c      2007-05-15 13:01:35.000000000 -0600
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 @@ -314,6 +363,12 @@ gssd_get_single_krb5_cred(krb5_context c
1966         /* set a short lifetime (for debugging only!) */
1967         printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
1968         krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
1969 +#else
1970 +       /* FIXME try to get the ticket with lifetime as long as possible,
1971 +        * to work around ticket-expiry + recovery problem in cmd3-11
1972 +        * remove this!!!
1973 +        */
1974 +       krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
1975  #endif
1976          if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
1977                                           kt, 0, NULL, &options))) {
1978 @@ -325,11 +380,7 @@ gssd_get_single_krb5_cred(krb5_context c
1979                             "principal '%s' from keytab '%s'\n",
1980                          error_message(code),
1981                          pname ? pname : "<unparsable>", kt_name);
1982 -#ifdef HAVE_KRB5
1983 -               if (pname) krb5_free_unparsed_name(context, pname);
1984 -#else
1985 -               if (pname) free(pname);
1986 -#endif
1987 +               if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
1988                 goto out;
1989         }
1990  
1991 @@ -378,15 +429,7 @@ gssd_get_single_krb5_cred(krb5_context c
1992         return (code);
1993  }
1994  
1995 -/*
1996 - * Determine if we already have a ple for the given realm
1997 - *
1998 - * Returns:
1999 - *     0 => no ple found for given realm
2000 - *     1 => found ple for given realm
2001 - */
2002 -static int
2003 -gssd_have_realm_ple(void *r)
2004 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
2005  {
2006         struct gssd_k5_kt_princ *ple;
2007  #ifdef HAVE_KRB5
2008 @@ -396,18 +439,76 @@ gssd_have_realm_ple(void *r)
2009  #endif
2010  
2011         for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
2012 -#ifdef HAVE_KRB5
2013 -               if ((realm->length == strlen(ple->realm)) &&
2014 -                   (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2015 -#else
2016 -               if (strcmp(realm, ple->realm) == 0) {
2017 -#endif
2018 -                   return 1;
2019 -               }
2020 +               if (KRB5_STRCMP(realm, ple->realm) == 0)
2021 +                   return ple;
2022 +       }
2023 +       return NULL;
2024 +}
2025 +
2026 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2027 +{
2028 +       if (ple->princ)
2029 +               krb5_free_principal(kctx, ple->princ);
2030 +       if (ple->realm)
2031 +               free(ple->realm);
2032 +       if (ple->ccname)
2033 +               free(ple->ccname);
2034 +       free(ple);
2035 +}
2036 +
2037 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2038 +{
2039 +       struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2040 +       struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
2041 +
2042 +       for (; ent; prev = &ent->next, ent = ent->next) {
2043 +               if (ent != ple)
2044 +                       continue;
2045 +
2046 +               *prev = ent->next;
2047 +               gssd_free_ple(kctx, ent);
2048 +               return 1;
2049         }
2050         return 0;
2051  }
2052  
2053 +static
2054 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2055 +                                        krb5_principal principal)
2056 +{
2057 +       struct gssd_k5_kt_princ *ple;
2058 +       krb5_error_code          code;
2059 +
2060 +       ple = malloc(sizeof(*ple));
2061 +       if (ple == NULL) {
2062 +               printerr(0, "ERROR: could not allocate storage "
2063 +                           "for principal list entry\n");
2064 +               return NULL;
2065 +       }
2066 +
2067 +       memset(ple, 0, sizeof(*ple));
2068 +
2069 +       ple->realm = KRB5_STRDUP(principal->realm);
2070 +       if (ple->realm == NULL) {
2071 +               printerr(0, "ERROR: not enough memory while copying realm to "
2072 +                           "principal list entry\n");
2073 +               goto err_free;
2074 +       }
2075 +
2076 +       code = krb5_copy_principal(kctx, principal, &ple->princ);
2077 +       if (code) {
2078 +               printerr(0, "ERROR: %s while copying principal "
2079 +                           "to principal list entry\n",
2080 +                        error_message(code));
2081 +               goto err_free;
2082 +       }
2083 +
2084 +       return ple;
2085 +err_free:
2086 +       gssd_free_ple(kctx, ple);
2087 +       return NULL;
2088 +}
2089 +
2090  /*
2091   * Process the given keytab file and create a list of principals we
2092   * might use to perform mount operations.
2093 @@ -451,82 +552,106 @@ gssd_process_krb5_keytab(krb5_context co
2094                 }
2095                 printerr(2, "Processing keytab entry for principal '%s'\n",
2096                          pname);
2097 -#ifdef HAVE_KRB5
2098 -               if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
2099 -                    (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
2100 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2101 -#else
2102 -               if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
2103 -                    (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
2104 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2105 -                             
2106 -#endif
2107 -                    (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
2108 -                       printerr(2, "We will use this entry (%s)\n", pname);
2109 -                       ple = malloc(sizeof(struct gssd_k5_kt_princ));
2110 -                       if (ple == NULL) {
2111 -                               printerr(0, "ERROR: could not allocate storage "
2112 -                                           "for principal list entry\n");
2113 -#ifdef HAVE_KRB5
2114 -                               krb5_free_unparsed_name(context, pname);
2115 -#else
2116 -                               free(pname);
2117 -#endif
2118 -                               retval = ENOMEM;
2119 -                               goto out;
2120 +
2121 +               /* mds service entry:
2122 +                *   - hostname and realm should match this node
2123 +                *   - replace existing non-mds entry of this realm
2124 +                */
2125 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
2126 +                       krb5_principal princ = kte.principal;
2127 +                       krb5_data *princ_host;
2128 +                       struct utsname utsbuf;
2129 +                       struct hostent *host;
2130 +
2131 +                       if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2132 +                                           this_realm) != 0) {
2133 +                               printerr(2, "alien mds service entry, skip\n");
2134 +                               goto next;
2135                         }
2136 -                       /* These will be filled in later */
2137 -                       ple->next = NULL;
2138 -                       ple->ccname = NULL;
2139 -                       ple->endtime = 0;
2140 -                       if ((ple->realm =
2141 -#ifdef HAVE_KRB5
2142 -                               strndup(kte.principal->realm.data,
2143 -                                       kte.principal->realm.length))
2144 -#else
2145 -                               strdup(kte.principal->realm))
2146 -#endif
2147 -                                       == NULL) {
2148 -                               printerr(0, "ERROR: %s while copying realm to "
2149 -                                           "principal list entry\n",
2150 -                                        "not enough memory");
2151 -#ifdef HAVE_KRB5
2152 -                               krb5_free_unparsed_name(context, pname);
2153 -#else
2154 -                               free(pname);
2155 -#endif
2156 -                               retval = ENOMEM;
2157 -                               goto out;
2158 +
2159 +                       princ_host = krb5_princ_component(context, princ, 1);
2160 +                       if (princ_host == NULL) {
2161 +                               printerr(2, "mds service entry: no hostname in "
2162 +                                        "principal, skip\n");
2163 +                               goto next;
2164                         }
2165 -                       if ((code = krb5_copy_principal(context,
2166 -                                       kte.principal, &ple->princ))) {
2167 -                               printerr(0, "ERROR: %s while copying principal "
2168 -                                           "to principal list entry\n",
2169 -                                       error_message(code));
2170 -#ifdef HAVE_KRB5
2171 -                               krb5_free_unparsed_name(context, pname);
2172 -#else
2173 -                               free(pname);
2174 -#endif
2175 -                               retval = code;
2176 -                               goto out;
2177 +
2178 +                       if (uname(&utsbuf)) {
2179 +                               printerr(2, "mds service entry: unable to get "
2180 +                                        "UTS name, skip\n");
2181 +                               goto next;
2182                         }
2183 -                       if (gssd_k5_kt_princ_list == NULL)
2184 -                               gssd_k5_kt_princ_list = ple;
2185 -                       else {
2186 -                               ple->next = gssd_k5_kt_princ_list;
2187 -                               gssd_k5_kt_princ_list = ple;
2188 +                       host = gethostbyname(utsbuf.nodename);
2189 +                       if (host == NULL) {
2190 +                               printerr(2, "mds service entry: unable to get "
2191 +                                        "local hostname, skip\n");
2192 +                               goto next;
2193                         }
2194 -               }
2195 -               else {
2196 +
2197 +                       if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
2198 +                               printerr(2, "mds service entry: hostname "
2199 +                                        "doesn't match: %s - %.*s, skip\n",
2200 +                                        host->h_name,
2201 +                                        princ_host->length, princ_host->data);
2202 +                               goto next;
2203 +                       }
2204 +
2205 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2206 +                       if (ple) {
2207 +                               if (ple->fl_mds) {
2208 +                                       printerr(2,"mds service entry: found a"
2209 +                                                "duplicated one, it's like a "
2210 +                                                "mis-configuration, skip\n");
2211 +                                       goto next;
2212 +                               }
2213 +
2214 +                               gssd_remove_ple(context, ple);
2215 +                               printerr(2, "mds service entry: replace an "
2216 +                                        "existed non-mds one\n");
2217 +                       }
2218 +               } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2219 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2220 +                       if (ple) {
2221 +                               if (ple->fl_mds || ple->fl_root) {
2222 +                                       printerr(2, "root entry: found a "
2223 +                                                "existed %s entry, skip\n",
2224 +                                                ple->fl_mds ? "mds" : "root");
2225 +                                       goto next;
2226 +                               }
2227 +
2228 +                               gssd_remove_ple(context, ple);
2229 +                               printerr(2, "root entry: replace an existed "
2230 +                                        "non-mds non-root one\n");
2231 +                       }
2232 +               } else {
2233                         printerr(2, "We will NOT use this entry (%s)\n",
2234                                 pname);
2235 +                       goto next;
2236                 }
2237 -#ifdef HAVE_KRB5
2238 -               krb5_free_unparsed_name(context, pname);
2239 -#else
2240 -               free(pname);
2241 -#endif
2242 +
2243 +               /* construct ple */
2244 +               printerr(2, "We will use this entry (%s)\n", pname);
2245 +               ple = gssd_create_ple(context, kte.principal);
2246 +               if (ple == NULL) {
2247 +                       KRB5_FREE_UNPARSED_NAME(context, pname);
2248 +                       goto out;
2249 +               }
2250 +
2251 +               /* add proper flags */
2252 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2253 +                       ple->fl_mds = 1;
2254 +               else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2255 +                       ple->fl_root = 1;
2256 +
2257 +               /* enqueue */
2258 +               if (gssd_k5_kt_princ_list == NULL)
2259 +                       gssd_k5_kt_princ_list = ple;
2260 +               else {
2261 +                       ple->next = gssd_k5_kt_princ_list;
2262 +                       gssd_k5_kt_princ_list = ple;
2263 +               }
2264 + next:
2265 +               KRB5_FREE_UNPARSED_NAME(context, pname);
2266         }
2267  
2268         if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
2269 @@ -642,6 +767,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
2270         printerr(2, "getting credentials for client with uid %u for "
2271                     "server %s\n", uid, servername);
2272         memset(buf, 0, sizeof(buf));
2273 +
2274         if (gssd_find_existing_krb5_ccache(uid, &d)) {
2275                 snprintf(buf, sizeof(buf), "FILE:%s/%s",
2276                         ccachedir, d->d_name);
2277 @@ -702,7 +828,7 @@ gssd_refresh_krb5_machine_creds(void)
2278                 goto out;
2279         }
2280  
2281 -       printerr(1, "Using keytab file '%s'\n", keytabfile);
2282 +       printerr(2, "Using keytab file '%s'\n", keytabfile);
2283  
2284         if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
2285                 printerr(0, "ERROR: %s while resolving keytab '%s'\n",
2286 @@ -717,12 +843,12 @@ gssd_refresh_krb5_machine_creds(void)
2287                 if (gssd_k5_kt_princ_list == NULL) {
2288                         printerr(0, "ERROR: No usable keytab entries found in "
2289                                     "keytab '%s'\n", keytabfile);
2290 -                       printerr(0, "Do you have a valid keytab entry for "
2291 -                                   "%s/<your.host>@<YOUR.REALM> in "
2292 +                       printerr(0, "You must have a valid keytab entry for "
2293 +                                   "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
2294 +                                   "and %s@<YOUR.REALM> on client nodes, in "
2295                                     "keytab file %s ?\n",
2296 -                                   GSSD_SERVICE_NAME, keytabfile);
2297 -                       printerr(0, "Continuing without (machine) credentials "
2298 -                                   "- nfs4 mounts with Kerberos will fail\n");
2299 +                                   GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
2300 +                                   keytabfile);
2301                 }
2302         }
2303  
2304 @@ -872,6 +998,7 @@ gssd_destroy_krb5_machine_creds(void)
2305         krb5_free_context(context);
2306  }
2307  
2308 +#if 0
2309  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2310  /*
2311   * this routine obtains a credentials handle via gss_acquire_cred()
2312 @@ -927,6 +1054,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2313         return 0;
2314  }
2315  #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2316 +#endif
2317  
2318  /*
2319   * Obtain supported enctypes from kernel.
2320 diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.h nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h
2321 --- nfs-utils-1.0.10/utils/gssd/krb5_util.h     2007-05-15 13:02:26.000000000 -0600
2322 +++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h      2007-05-15 13:01:35.000000000 -0600
2323 @@ -10,6 +10,8 @@
2324  struct gssd_k5_kt_princ {
2325         struct gssd_k5_kt_princ *next;
2326         krb5_principal princ;
2327 +       unsigned int    fl_root:1,
2328 +                       fl_mds:1;
2329         char *ccname;
2330         char *realm;
2331         krb5_timestamp endtime;
2332 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2333  void gssd_obtain_kernel_krb5_info(void);
2334  
2335  
2336 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2337 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2338 -#endif
2339 -
2340  #endif /* KRB5_UTIL_H */
2341 diff -rNup nfs-utils-1.0.10/utils/gssd/lgss_keyring.c nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c
2342 --- nfs-utils-1.0.10/utils/gssd/lgss_keyring.c  1969-12-31 17:00:00.000000000 -0700
2343 +++ nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c   2007-05-15 13:01:35.000000000 -0600
2344 @@ -0,0 +1,776 @@
2345 +/*
2346 + *  lucall_keyring.c
2347 + *  user-space upcall to create GSS context, using keyring interface to kernel
2348 + *
2349 + *  Copyright (c) 2007 Cluster File Systems, Inc.
2350 + *   Author: Eric Mei <ericm@clusterfs.com>
2351 + *
2352 + *   This file is part of the Lustre file system, http://www.lustre.org
2353 + *   Lustre is a trademark of Cluster File Systems, Inc.
2354 + *
2355 + *   You may have signed or agreed to another license before downloading
2356 + *   this software.  If so, you are bound by the terms and conditions
2357 + *   of that agreement, and the following does not apply to you.  See the
2358 + *   LICENSE file included with this distribution for more information.
2359 + *
2360 + *   If you did not agree to a different license, then this copy of Lustre
2361 + *   is open source software; you can redistribute it and/or modify it
2362 + *   under the terms of version 2 of the GNU General Public License as
2363 + *   published by the Free Software Foundation.
2364 + *
2365 + *   In either case, Lustre is distributed in the hope that it will be
2366 + *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
2367 + *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2368 + *   license text for more details.
2369 + */
2370 +
2371 +#include <unistd.h>
2372 +#include <stdlib.h>
2373 +#include <stdio.h>
2374 +#include <fcntl.h>
2375 +#include <string.h>
2376 +#include <errno.h>
2377 +#include <stdarg.h>
2378 +#include <syslog.h>
2379 +#include <assert.h>
2380 +#include <pwd.h>
2381 +#include <keyutils.h>
2382 +#include <gssapi/gssapi.h>
2383 +
2384 +#include <libcfs/libcfs.h>
2385 +
2386 +#include "lsupport.h"
2387 +#include "write_bytes.h"
2388 +#include "krb5_util.h"
2389 +#include "gss_oids.h"
2390 +#include "context.h"
2391 +
2392 +/*
2393 + * XXX TEMP to satisfy link. should be removed!!!
2394 + */
2395 +char ccachedir[PATH_MAX] = "/tmp";
2396 +char keytabfile[PATH_MAX] = "/etc/krb5.keytab";
2397 +int  use_memcache = 0;
2398 +
2399 +/****************************************
2400 + * log facilities                       *
2401 + ****************************************/
2402 +
2403 +/*
2404 + * log level:
2405 + * 0: critical error messages
2406 + * 1: warning included
2407 + * 2: debugging
2408 + * 3: excessive messages
2409 + */
2410 +typedef enum {
2411 +        LL_ERR          = 0,
2412 +        LL_WARN         = 1,
2413 +        LL_INFO         = 2,
2414 +        LL_TRACE        = 3,
2415 +} loglevel_t;
2416 +
2417 +loglevel_t g_log_level = LL_TRACE;
2418 +
2419 +static void logmsg(loglevel_t level, const char *format, ...)
2420 +{
2421 +        char    buf[1024];
2422 +        int     offset;
2423 +        va_list ap;
2424 +
2425 +        if (level > g_log_level)
2426 +                return;
2427 +
2428 +        offset = snprintf(buf, sizeof(buf), "[%d]: ", getpid());
2429 +
2430 +        va_start(ap, format);
2431 +        vsnprintf(buf + offset, sizeof(buf) - offset, format, ap);
2432 +        va_end(ap);
2433 +
2434 +        syslog(LOG_INFO, "%s", buf);
2435 +}
2436 +
2437 +static void logmsg_gss(loglevel_t level, const gss_OID mech,
2438 +                       u_int32_t major, u_int32_t minor,
2439 +                       const char *format, ...)
2440 +{
2441 +        va_list         ap;
2442 +        u_int32_t       maj_stat1, min_stat1;
2443 +        u_int32_t       maj_stat2, min_stat2;
2444 +        gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER;
2445 +        gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER;
2446 +        char            maj_buf[30], min_buf[30];
2447 +        char           *maj, *min;
2448 +        uint32_t        msg_ctx = 0;
2449 +
2450 +        if (level > g_log_level)
2451 +                return;
2452 +
2453 +        /* Get major status message */
2454 +        maj_stat1 = gss_display_status(&min_stat1, major,
2455 +                GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf);
2456 +
2457 +        if (maj_stat1 != GSS_S_COMPLETE) {
2458 +                snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major);
2459 +                maj = &maj_buf[0];
2460 +        } else {
2461 +                maj = maj_gss_buf.value;
2462 +        }
2463 +
2464 +        /* Get minor status message */
2465 +        maj_stat2 = gss_display_status(&min_stat2, minor,
2466 +                GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf);
2467 +
2468 +        if (maj_stat2 != GSS_S_COMPLETE) {
2469 +                snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor);
2470 +                min = &min_buf[0];
2471 +        } else {
2472 +                min = min_gss_buf.value;
2473 +        }
2474 +
2475 +        syslog(LOG_INFO, "GSS-API: %s - %s\n", maj, min);
2476 +
2477 +        va_start(ap, format);
2478 +        vsyslog(LOG_INFO, format, ap);
2479 +        va_end(ap);
2480 +
2481 +        if (maj_gss_buf.length != 0)
2482 +                (void) gss_release_buffer(&min_stat1, &maj_gss_buf);
2483 +        if (min_gss_buf.length != 0)
2484 +                (void) gss_release_buffer(&min_stat2, &min_gss_buf);
2485 +}
2486 +
2487 +#define lassert(exp)                                                    \
2488 +        {                                                               \
2489 +                if ((int)(exp) == 0) {                                  \
2490 +                        logmsg(LL_ERR, "ASSERTION FAILED: #exp");       \
2491 +                        exit(-1);                                       \
2492 +                }                                                       \
2493 +        }
2494 +
2495 +/****************************************
2496 + * global declaration                   *
2497 + ****************************************/
2498 +
2499 +typedef enum {
2500 +        LGSS_SVC_MDS    = 0,
2501 +        LGSS_SVC_OSS    = 1,
2502 +        LGSS_SVC_MAX
2503 +} lgss_svc_t;
2504 +
2505 +const char *lgss_svc_name[LGSS_SVC_MAX] = {
2506 +        [LGSS_SVC_MDS] = "lustre_mds",
2507 +        [LGSS_SVC_OSS] = "lustre_oss",
2508 +};
2509 +
2510 +typedef enum {
2511 +        LGSS_AUTH_KRB5,
2512 +} lgss_auth_t;
2513 +
2514 +/*
2515 + * all data about negotiation
2516 + */
2517 +struct lgss_nego_data {
2518 +        uint32_t        lnd_established:1;
2519 +        uint32_t        lnd_uid;
2520 +        uint32_t        lnd_lsvc;
2521 +        char           *lnd_uuid;
2522 +
2523 +        gss_OID         lnd_mech;               /* mech OID */
2524 +        gss_name_t      lnd_svc_name;           /* service name */
2525 +        u_int           lnd_req_flags;          /* request flags */
2526 +        gss_cred_id_t   lnd_cred;               /* credential */
2527 +        gss_ctx_id_t    lnd_ctx;                /* session context */
2528 +        gss_buffer_desc lnd_rmt_ctx;            /* remote handle of context */
2529 +        uint32_t        lnd_seq_win;            /* sequence window */
2530 +
2531 +        int             lnd_rpc_err;
2532 +        int             lnd_gss_err;
2533 +};
2534 +
2535 +/*
2536 + * context creation response
2537 + */
2538 +struct lgss_init_res {
2539 +        gss_buffer_desc gr_ctx;         /* context handle */
2540 +        u_int           gr_major;       /* major status */
2541 +        u_int           gr_minor;       /* minor status */
2542 +        u_int           gr_win;         /* sequence window */
2543 +        gss_buffer_desc gr_token;       /* token */
2544 +};
2545 +
2546 +struct keyring_upcall_param {
2547 +        uint32_t        kup_ver;
2548 +        uint32_t        kup_uid;
2549 +        uint32_t        kup_gid;
2550 +        uint32_t        kup_svc;
2551 +        uint64_t        kup_nid;
2552 +        char            kup_tgt[64];
2553 +};
2554 +
2555 +/*
2556 + * gss target string of lustre service we are negotiating for
2557 + */
2558 +char *g_service = NULL;
2559 +
2560 +/****************************************
2561 + * child process: gss negotiation       *
2562 + ****************************************/
2563 +
2564 +#define INIT_CHANNEL    "/proc/fs/lustre/sptlrpc/gss/init_channel"
2565 +
2566 +int do_nego_rpc(struct lgss_nego_data *lnd,
2567 +                gss_buffer_desc *gss_token,
2568 +                struct lgss_init_res *gr)
2569 +{
2570 +        struct lgssd_ioctl_param  param;
2571 +        struct passwd            *pw;
2572 +        int                       fd, ret, res;
2573 +        char                      outbuf[8192];
2574 +        unsigned int             *p;
2575 +
2576 +        logmsg(LL_TRACE, "do_nego_rpc: get started\n");
2577 +
2578 +        pw = getpwuid(lnd->lnd_uid);
2579 +        if (!pw) {
2580 +                logmsg(LL_ERR, "no uid %u in local user database\n",
2581 +                       lnd->lnd_uid);
2582 +                return -1;
2583 +        }
2584 +
2585 +        param.version = GSSD_INTERFACE_VERSION;
2586 +        param.uuid = lnd->lnd_uuid;
2587 +        param.lustre_svc = lnd->lnd_lsvc;
2588 +        param.uid = lnd->lnd_uid;
2589 +        param.gid = pw->pw_gid;
2590 +        param.send_token_size = gss_token->length;
2591 +        param.send_token = (char *) gss_token->value;
2592 +        param.reply_buf_size = sizeof(outbuf);
2593 +        param.reply_buf = outbuf;
2594 +
2595 +        logmsg(LL_TRACE, "to open " INIT_CHANNEL "\n");
2596 +
2597 +        fd = open(INIT_CHANNEL, O_WRONLY);
2598 +        if (fd < 0) {
2599 +                logmsg(LL_ERR, "can't open " INIT_CHANNEL "\n");
2600 +                return -1;
2601 +        }
2602 +
2603 +        logmsg(LL_TRACE, "to down-write\n");
2604 +
2605 +        ret = write(fd, &param, sizeof(param));
2606 +        if (ret != sizeof(param)) {
2607 +                logmsg(LL_ERR, "lustre ioctl err: %d\n", strerror(errno));
2608 +                close(fd);
2609 +                return -1;
2610 +        }
2611 +        close(fd);
2612 +
2613 +        logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n");
2614 +        if (param.status) {
2615 +                logmsg(LL_ERR, "status: %d (%s)\n",
2616 +                       param.status, strerror((int)param.status));
2617 +
2618 +                if (param.status == -ETIMEDOUT) {
2619 +                        /* kernel return -ETIMEDOUT means the rpc timedout,
2620 +                         * we should notify the caller to reinitiate the
2621 +                         * gss negotiation, by return -ERESTART
2622 +                         */
2623 +                        lnd->lnd_rpc_err = -ERESTART;
2624 +                        lnd->lnd_gss_err = 0;
2625 +                } else {
2626 +                        lnd->lnd_rpc_err = param.status;
2627 +                        lnd->lnd_gss_err = 0;
2628 +                }
2629 +
2630 +                return -1;
2631 +        }
2632 +
2633 +        p = (unsigned int *)outbuf;
2634 +        res = *p++;
2635 +        gr->gr_major = *p++;
2636 +        gr->gr_minor = *p++;
2637 +        gr->gr_win = *p++;
2638 +
2639 +        gr->gr_ctx.length = *p++;
2640 +        gr->gr_ctx.value = malloc(gr->gr_ctx.length);
2641 +        memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
2642 +        p += (((gr->gr_ctx.length + 3) & ~3) / 4);
2643 +
2644 +        gr->gr_token.length = *p++;
2645 +        gr->gr_token.value = malloc(gr->gr_token.length);
2646 +        memcpy(gr->gr_token.value, p, gr->gr_token.length);
2647 +        p += (((gr->gr_token.length + 3) & ~3) / 4);
2648 +
2649 +        logmsg(LL_INFO, "do_nego_rpc: receive handle len %d, token len %d\n",
2650 +               gr->gr_ctx.length, gr->gr_token.length);
2651 +        return 0;
2652 +}
2653 +
2654 +/*
2655 + * if return error, the lnd_rpc_err or lnd_gss_err is set.
2656 + */
2657 +int lgssc_negotiation(struct lgss_nego_data *lnd)
2658 +{
2659 +        struct lgss_init_res    gr;
2660 +        gss_buffer_desc        *recv_tokenp, send_token;
2661 +        OM_uint32               maj_stat, min_stat, ret_flags;
2662 +        int                     call_stat;
2663 +
2664 +        logmsg(LL_TRACE, "start negotiation\n");
2665 +
2666 +        /* GSS context establishment loop. */
2667 +        memset(&gr, 0, sizeof(gr));
2668 +        recv_tokenp = GSS_C_NO_BUFFER;
2669 +
2670 +        for (;;) {
2671 +#if 0
2672 +                /* print the token we just received */
2673 +                if (recv_tokenp != GSS_C_NO_BUFFER) {
2674 +                        printerr(3, "The received token length %d\n",
2675 +                                 recv_tokenp->length);
2676 +                        print_hexl(3, recv_tokenp->value, recv_tokenp->length);
2677 +                }
2678 +#endif
2679 +
2680 +                maj_stat = gss_init_sec_context(&min_stat,
2681 +                                                lnd->lnd_cred,
2682 +                                                &lnd->lnd_ctx,
2683 +                                                lnd->lnd_svc_name,
2684 +                                                lnd->lnd_mech,
2685 +                                                lnd->lnd_req_flags,
2686 +                                                0,            /* time req */
2687 +                                                NULL,         /* channel */
2688 +                                                recv_tokenp,
2689 +                                                NULL,         /* used mech */
2690 +                                                &send_token,
2691 +                                                &ret_flags,
2692 +                                                NULL);        /* time rec */
2693 +
2694 +                if (recv_tokenp != GSS_C_NO_BUFFER) {
2695 +                        gss_release_buffer(&min_stat, &gr.gr_token);
2696 +                        recv_tokenp = GSS_C_NO_BUFFER;
2697 +                }
2698 +
2699 +                if (maj_stat != GSS_S_COMPLETE &&
2700 +                    maj_stat != GSS_S_CONTINUE_NEEDED) {
2701 +                        lnd->lnd_gss_err = maj_stat;
2702 +
2703 +                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2704 +                                   "failed init context\n");
2705 +                        break;
2706 +                }
2707 +
2708 +                if (send_token.length != 0) {
2709 +                        memset(&gr, 0, sizeof(gr));
2710 +#if 0
2711 +                        /* print the token we are about to send */
2712 +                        printerr(3, "token being sent length %d\n",
2713 +                                 send_token.length);
2714 +                        print_hexl(3, send_token.value, send_token.length);
2715 +#endif
2716 +                        call_stat = do_nego_rpc(lnd, &send_token, &gr);
2717 +                        gss_release_buffer(&min_stat, &send_token);
2718 +
2719 +                        if (call_stat != 0 ||
2720 +                            (gr.gr_major != GSS_S_COMPLETE &&
2721 +                             gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
2722 +                                lnd->lnd_rpc_err = call_stat;
2723 +                                lnd->lnd_gss_err = gr.gr_major;
2724 +
2725 +                                logmsg(LL_ERR, "call stat %d, major stat %x\n",
2726 +                                       call_stat, gr.gr_major);
2727 +                                return -1;
2728 +                        }
2729 +
2730 +                        if (gr.gr_ctx.length != 0) {
2731 +                                if (lnd->lnd_rmt_ctx.value)
2732 +                                        gss_release_buffer(&min_stat,
2733 +                                                           &lnd->lnd_rmt_ctx);
2734 +                                lnd->lnd_rmt_ctx = gr.gr_ctx;
2735 +                        }
2736 +
2737 +                        if (gr.gr_token.length != 0) {
2738 +                                if (maj_stat != GSS_S_CONTINUE_NEEDED)
2739 +                                        break;
2740 +                                recv_tokenp = &gr.gr_token;
2741 +                        }
2742 +                }
2743 +
2744 +                /* GSS_S_COMPLETE => check gss header verifier,
2745 +                 * usually checked in gss_validate
2746 +                 */
2747 +                if (maj_stat == GSS_S_COMPLETE) {
2748 +                        lnd->lnd_established = 1;
2749 +                        lnd->lnd_seq_win = gr.gr_win;
2750 +                        break;
2751 +                }
2752 +        }
2753 +
2754 +        /* End context negotiation loop. */
2755 +        if (!lnd->lnd_established) {
2756 +                if (gr.gr_token.length != 0)
2757 +                        gss_release_buffer(&min_stat, &gr.gr_token);
2758 +
2759 +                if (lnd->lnd_gss_err == GSS_S_COMPLETE)
2760 +                        lnd->lnd_rpc_err = -EACCES;
2761 +
2762 +                logmsg(LL_ERR, "context negotiation failed\n");
2763 +                return -1;
2764 +        }
2765 +
2766 +        logmsg(LL_INFO, "successfully negotiated context\n");
2767 +        return 0;
2768 +}
2769 +
2770 +int construct_service(struct keyring_upcall_param *kup)
2771 +{
2772 +        const int       max_namelen = 512;
2773 +        char            namebuf[max_namelen];
2774 +        int             alloc_size;
2775 +
2776 +        lassert(g_service == NULL);
2777 +
2778 +        if (kup->kup_svc >= LGSS_SVC_MAX) {
2779 +                logmsg(LL_ERR, "invalid lgss service %d\n", kup->kup_svc);
2780 +                return 1;
2781 +        }
2782 +
2783 +        if (lnet_nid2hostname(kup->kup_nid, namebuf, max_namelen))
2784 +                return 1;
2785 +
2786 +        alloc_size = 32 + strlen(namebuf);
2787 +
2788 +        g_service = malloc(alloc_size);
2789 +        if (g_service == NULL) {
2790 +                logmsg(LL_ERR, "can't malloc %d bytes\n", alloc_size);
2791 +                return 1;
2792 +        }
2793 +
2794 +        snprintf(g_service, alloc_size, "%s@%s",
2795 +                 lgss_svc_name[kup->kup_svc], namebuf);
2796 +
2797 +        logmsg(LL_INFO, "constructed service: %s\n", g_service);
2798 +        return 0;
2799 +}
2800 +
2801 +/*
2802 + * if return error, the lnd_rpc_err or lnd_gss_err is set.
2803 + */
2804 +int lgssc_init_nego_data(struct lgss_nego_data *lnd,
2805 +                         struct keyring_upcall_param *kup,
2806 +                         lgss_auth_t authtype)
2807 +{
2808 +        gss_buffer_desc         sname;
2809 +        OM_uint32               maj_stat, min_stat;
2810 +
2811 +        memset(lnd, 0, sizeof(*lnd));
2812 +
2813 +        lnd->lnd_uid = kup->kup_uid;
2814 +        lnd->lnd_lsvc = kup->kup_svc;
2815 +        lnd->lnd_uuid = kup->kup_tgt;
2816 +
2817 +        lnd->lnd_established = 0;
2818 +        lnd->lnd_svc_name = GSS_C_NO_NAME;
2819 +        lnd->lnd_cred = GSS_C_NO_CREDENTIAL;
2820 +        lnd->lnd_ctx = GSS_C_NO_CONTEXT;
2821 +        lnd->lnd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
2822 +        lnd->lnd_seq_win = 0;
2823 +
2824 +        switch (authtype) {
2825 +        case LGSS_AUTH_KRB5:
2826 +                lnd->lnd_mech = (gss_OID) &krb5oid;
2827 +                lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG;
2828 +                break;
2829 +        default:
2830 +                logmsg(LL_ERR, "invalid auth type: %d\n", authtype);
2831 +                lnd->lnd_rpc_err = -EACCES;
2832 +                return -1;
2833 +        }
2834 +
2835 +        sname.value = g_service;
2836 +        sname.length = strlen(g_service);
2837 +
2838 +        maj_stat = gss_import_name(&min_stat, &sname,
2839 +                                   (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
2840 +                                   &lnd->lnd_svc_name);
2841 +        if (maj_stat != GSS_S_COMPLETE) {
2842 +                logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2843 +                           "can't import svc name\n");
2844 +                lnd->lnd_gss_err = maj_stat;
2845 +                return -1;
2846 +        }
2847 +
2848 +        return 0;
2849 +}
2850 +
2851 +void lgssc_fini_nego_data(struct lgss_nego_data *lnd)
2852 +{
2853 +        OM_uint32       maj_stat, min_stat;
2854 +
2855 +        if (lnd->lnd_svc_name != GSS_C_NO_NAME) {
2856 +                maj_stat = gss_release_name(&min_stat, &lnd->lnd_svc_name);
2857 +                if (maj_stat != GSS_S_COMPLETE)
2858 +                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2859 +                                   "can't release service name\n");
2860 +        }
2861 +
2862 +        if (lnd->lnd_cred != GSS_C_NO_CREDENTIAL) {
2863 +                maj_stat = gss_release_cred(&min_stat, &lnd->lnd_cred);
2864 +                if (maj_stat != GSS_S_COMPLETE)
2865 +                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
2866 +                                   "can't release credential\n");
2867 +        }
2868 +}
2869 +
2870 +static
2871 +int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error)
2872 +{
2873 +        int      seqwin = 0;
2874 +        char     buf[32];
2875 +        char    *p, *end;
2876 +
2877 +        logmsg(LL_TRACE, "revoking kernel key 0x%x\n", keyid);
2878 +
2879 +        p = buf;
2880 +        end = buf + sizeof(buf);
2881 +
2882 +        WRITE_BYTES(&p, end, seqwin);
2883 +        WRITE_BYTES(&p, end, rpc_error);
2884 +        WRITE_BYTES(&p, end, gss_error);
2885 +
2886 +again:
2887 +        if (keyctl_update(keyid, buf, p - buf)) {
2888 +                if (errno != EAGAIN) {
2889 +                        logmsg(LL_ERR, "failed to revoke key 0x%x: %s\n",
2890 +                               keyid, strerror(errno));
2891 +                        return -1;
2892 +                }
2893 +
2894 +                logmsg(LL_WARN, "revoke key 0x%x too soon, try again\n", keyid);
2895 +                sleep(2);
2896 +                goto again;
2897 +        }
2898 +
2899 +        logmsg(LL_INFO, "successfully revoke key 0x%x\n", keyid);
2900 +        return 0;
2901 +}
2902 +
2903 +static
2904 +int update_kernel_key(key_serial_t keyid,
2905 +                      struct lgss_nego_data *lnd,
2906 +                      gss_buffer_desc *ctx_token)
2907 +{
2908 +        char        *buf = NULL, *p = NULL, *end = NULL;
2909 +        unsigned int buf_size = 0;
2910 +        int          rc;
2911 +
2912 +        logmsg(LL_TRACE, "updating kernel key 0x%x\n", keyid);
2913 +
2914 +        buf_size = sizeof(lnd->lnd_seq_win) +
2915 +                   sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length +
2916 +                   sizeof(ctx_token->length) + ctx_token->length;
2917 +        buf = malloc(buf_size);
2918 +        if (buf == NULL) {
2919 +                logmsg(LL_ERR, "failed to alloc key update buf: size %d\n",
2920 +                       buf_size);
2921 +                return 1;
2922 +        }
2923 +
2924 +        p = buf;
2925 +        end = buf + buf_size;
2926 +        rc = -1;
2927 +
2928 +        if (WRITE_BYTES(&p, end, lnd->lnd_seq_win))
2929 +                goto out;
2930 +        if (write_buffer(&p, end, &lnd->lnd_rmt_ctx))
2931 +                goto out;
2932 +        if (write_buffer(&p, end, ctx_token))
2933 +                goto out;
2934 +
2935 +again:
2936 +        if (keyctl_update(keyid, buf, p - buf)) {
2937 +                if (errno != EAGAIN) {
2938 +                        logmsg(LL_ERR, "failed to update key 0x%x: %s\n",
2939 +                               keyid, strerror(errno));
2940 +                        goto out;
2941 +                }
2942 +
2943 +                logmsg(LL_WARN, "update key 0x%x too soon, try again\n", keyid);
2944 +                sleep(2);
2945 +                goto again;
2946 +        }
2947 +
2948 +        rc = 0;
2949 +        logmsg(LL_INFO, "successfully updated key 0x%x\n", keyid);
2950 +out:
2951 +        free(buf);
2952 +        return rc;
2953 +}
2954 +
2955 +/*
2956 + * note we can't assume authority in child process
2957 + */
2958 +int lgssc_kr_negotiate(key_serial_t keyid, struct keyring_upcall_param *kup)
2959 +{
2960 +        struct lgss_nego_data   lnd;
2961 +        gss_buffer_desc         token = GSS_C_EMPTY_BUFFER;
2962 +        OM_uint32               min_stat;
2963 +        int                     rc;
2964 +
2965 +        logmsg(LL_TRACE, "child start on behalf of key 0x%x\n", keyid);
2966 +
2967 +        if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) {
2968 +                logmsg(LL_ERR, "key 0x%x, failed set gids to %u: %s\n",
2969 +                       keyid, kup->kup_gid, strerror(errno));
2970 +        }
2971 +
2972 +        if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) {
2973 +                logmsg(LL_ERR, "key 0x%x, failed set uids to %u: %s\n",
2974 +                       keyid, kup->kup_uid, strerror(errno));
2975 +        }
2976 +
2977 +        /*
2978 +         * link to session keyring, allow the key to be found.
2979 +         */
2980 +        if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) {
2981 +                logmsg(LL_ERR, "key 0x%x, failed to link to session "
2982 +                       "keyring: %s\n", keyid, strerror(errno));
2983 +                error_kernel_key(keyid, -EACCES, 0);
2984 +                return -1;
2985 +        }
2986 +
2987 +        rc = -1;
2988 +        if (construct_service(kup)) {
2989 +                error_kernel_key(keyid, -EACCES, 0);
2990 +                goto out_unlink;
2991 +        }
2992 +
2993 +        if (1/* kup->kup_uid == 0 FIXME */) {
2994 +                gssd_setup_krb5_user_gss_ccache(kup->kup_uid, g_service);
2995 +        }
2996 +
2997 +        if (lgssc_init_nego_data(&lnd, kup, LGSS_AUTH_KRB5)) {
2998 +                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
2999 +                goto out_unlink;
3000 +        }
3001 +
3002 +        rc = lgssc_negotiation(&lnd);
3003 +        if (rc) {
3004 +                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
3005 +                goto out;
3006 +        }
3007 +
3008 +        rc = serialize_context_for_kernel(lnd.lnd_ctx, &token, lnd.lnd_mech);
3009 +        if (rc) {
3010 +                error_kernel_key(keyid, rc, lnd.lnd_gss_err);
3011 +
3012 +                logmsg(LL_ERR, "failed to export context\n");
3013 +                goto out;
3014 +        }
3015 +
3016 +        rc = update_kernel_key(keyid,  &lnd, &token);
3017 +        if (rc)
3018 +                goto out;
3019 +
3020 +        rc = 0;
3021 +        logmsg(LL_INFO, "key update OK!\n");
3022 +out:
3023 +        if (token.length != 0)
3024 +                gss_release_buffer(&min_stat, &token);
3025 +
3026 +        lgssc_fini_nego_data(&lnd);
3027 +
3028 +out_unlink:
3029 +        if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) {
3030 +                logmsg(LL_ERR, "failed to unlink key %d: %s\n",
3031 +                       keyid, strerror(errno));
3032 +        }
3033 +
3034 +        return rc;
3035 +}
3036 +
3037 +/****************************************
3038 + * main process                         *
3039 + ****************************************/
3040 +
3041 +int main(int argc, char *argv[])
3042 +{
3043 +        struct keyring_upcall_param     uparam;
3044 +        key_serial_t                    keyid;
3045 +        key_serial_t                    /*tring, pring, */sring;
3046 +        key_serial_t                    inst_keyring;
3047 +        int                             is_root;
3048 +        pid_t                           child;
3049 +
3050 +        if (argc != 10 + 1) {
3051 +                logmsg(LL_ERR, "Invalid parameter number %d\n", argc);
3052 +                return 1;
3053 +        }
3054 +
3055 +#if 0
3056 +        logmsg(LL_TRACE, "OP:       %s\n", argv[1]);
3057 +        logmsg(LL_TRACE, "KeyID:    %s\n", argv[2]);
3058 +        logmsg(LL_TRACE, "KeyType:  %s\n", argv[3]);
3059 +        logmsg(LL_TRACE, "KeyDesc:  %s\n", argv[4]);
3060 +        logmsg(LL_TRACE, "COInfo:   %s\n", argv[5]);
3061 +        logmsg(LL_TRACE, "UID:      %s\n", argv[6]);
3062 +        logmsg(LL_TRACE, "GID:      %s\n", argv[7]);
3063 +        logmsg(LL_TRACE, "TKeyring: %s\n", argv[8]);
3064 +        logmsg(LL_TRACE, "PKeyring: %s\n", argv[9]);
3065 +        logmsg(LL_TRACE, "SKeyring: %s\n", argv[10]);
3066 +#endif
3067 +        logmsg(LL_INFO, "[%u/%u]: key %s, desc %s, uid %s, sring %s\n",
3068 +               getuid(), geteuid(),
3069 +               argv[2], argv[4], argv[6], argv[10]);
3070 +
3071 +        memset(&uparam, 0, sizeof(uparam));
3072 +
3073 +        if (strcmp(argv[1], "create") != 0) {
3074 +                logmsg(LL_ERR, "invalid OP %s\n", argv[1]);
3075 +                return 1;
3076 +        }
3077 +
3078 +        if (sscanf(argv[2], "%d", &keyid) != 1) {
3079 +                logmsg(LL_ERR, "can't extract KeyID\n");
3080 +                return 1;
3081 +        }
3082 +
3083 +        if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) {
3084 +                logmsg(LL_ERR, "can't extract uid\n");
3085 +                return 1;
3086 +        }
3087 +
3088 +        if (sscanf(argv[10], "%d", &sring) != 1) {
3089 +                logmsg(LL_ERR, "can't extract session keyring\n");
3090 +                return 1;
3091 +        }
3092 +
3093 +        if (sscanf(argv[5], "%d:%d:%Lx:%s", &is_root, &uparam.kup_svc,
3094 +                   &uparam.kup_nid, uparam.kup_tgt) != 4) {
3095 +                logmsg(LL_ERR, "can't extract callout info: %s\n", argv[5]);
3096 +                return 1;
3097 +        }
3098 +        logmsg(LL_INFO, "coinfo: fl %d, svc %d, nid 0x%Lx, tgt %s\n",
3099 +               is_root, uparam.kup_svc, uparam.kup_nid, uparam.kup_tgt);
3100 +
3101 +        if (is_root)
3102 +                inst_keyring = 0;
3103 +        else
3104 +                inst_keyring = KEY_SPEC_SESSION_KEYRING;
3105 +
3106 +        if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
3107 +                logmsg(LL_ERR, "key instantiate: %s\n", strerror(errno));
3108 +                return 1;
3109 +        }
3110 +
3111 +        child = fork();
3112 +        if (child == -1) {
3113 +                logmsg(LL_ERR, "can't create child: %s\n", strerror(errno));
3114 +                return 1;
3115 +        } else if (child == 0) {
3116 +                return lgssc_kr_negotiate(keyid, &uparam);
3117 +        }
3118 +
3119 +        return 0;
3120 +}
3121 diff -rNup nfs-utils-1.0.10/utils/gssd/l_idmap.c nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c
3122 --- nfs-utils-1.0.10/utils/gssd/l_idmap.c       1969-12-31 17:00:00.000000000 -0700
3123 +++ nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c        2007-05-15 13:01:35.000000000 -0600
3124 @@ -0,0 +1,37 @@
3125 +#include <sys/types.h>
3126 +#include <stdlib.h>
3127 +#include <stdio.h>
3128 +
3129 +#include "lsupport.h"
3130 +
3131 +int main(int argc, char **argv)
3132 +{
3133 +       lnet_nid_t nid;
3134 +       uid_t uid;
3135 +       int rc;
3136 +
3137 +       if (argc < 3) {
3138 +               printf("Usage:\n"
3139 +                      "%s <princ> <nid>\n",
3140 +                      basename(argv[0]));
3141 +               return 1;
3142 +       }
3143 +
3144 +       nid = libcfs_str2nid(argv[2]);
3145 +       if (nid == LNET_NID_ANY) {
3146 +               printf("parse nid %s failed\n", argv[2]);
3147 +               return 1;
3148 +       }
3149 +       rc = lookup_mapping(argv[1], nid, &uid);
3150 +       if (rc == -1) {
3151 +               printf("lookup mapping failed\n");
3152 +               return 1;
3153 +       }
3154 +
3155 +       printf("principal: %s\n"
3156 +              "nid:       %#llx\n"
3157 +              "uid:       %u\n",
3158 +              argv[1], nid, uid);
3159 +
3160 +       return 0;
3161 +}
3162 diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.c nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c
3163 --- nfs-utils-1.0.10/utils/gssd/lsupport.c      1969-12-31 17:00:00.000000000 -0700
3164 +++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c       2007-05-15 13:01:35.000000000 -0600
3165 @@ -0,0 +1,781 @@
3166 +/*
3167 + *  Copyright (c) 2005 Cluster File Systems, Inc.
3168 + *
3169 + *   This file is part of Lustre, http://www.lustre.org.
3170 + *
3171 + *   Lustre is free software; you can redistribute it and/or
3172 + *   modify it under the terms of version 2 of the GNU General Public
3173 + *   License as published by the Free Software Foundation.
3174 + *
3175 + *   Lustre is distributed in the hope that it will be useful,
3176 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
3177 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3178 + *   GNU General Public License for more details.
3179 + *
3180 + *   You should have received a copy of the GNU General Public License
3181 + *   along with Lustre; if not, write to the Free Software
3182 + *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3183 + */
3184 +
3185 +#ifndef _GNU_SOURCE
3186 +#define _GNU_SOURCE
3187 +#endif
3188 +#include "config.h"
3189 +#include <sys/param.h>
3190 +#include <sys/utsname.h>
3191 +#include <sys/stat.h>
3192 +#include <sys/socket.h>
3193 +#include <arpa/inet.h>
3194 +#include <sys/types.h>
3195 +#include <sys/ipc.h>
3196 +#include <sys/sem.h>
3197 +
3198 +#include <stdio.h>
3199 +#include <stdlib.h>
3200 +#include <pwd.h>
3201 +#include <grp.h>
3202 +#include <string.h>
3203 +#include <dirent.h>
3204 +#include <poll.h>
3205 +#include <fcntl.h>
3206 +#include <signal.h>
3207 +#include <unistd.h>
3208 +#include <errno.h>
3209 +#include <assert.h>
3210 +#ifdef HAVE_GETHOSTBYNAME
3211 +# include <netdb.h>
3212 +#endif
3213 +
3214 +#include "err_util.h"
3215 +#include "gssd.h"
3216 +#include "lsupport.h"
3217 +
3218 +/****************************************
3219 + * exclusive startup                    *
3220 + ****************************************/
3221 +
3222 +static struct __sem_s {
3223 +        char           *name;
3224 +        key_t           sem_key;
3225 +        int             sem_id;
3226 +} sems[2] = {
3227 +        [GSSD_CLI] = { "client",  0x3a92d473, 0 },
3228 +        [GSSD_SVC] = { "server",  0x3b92d473, 0 },
3229 +};
3230 +
3231 +void gssd_init_unique(int type)
3232 +{
3233 +        struct __sem_s *sem = &sems[type];
3234 +        struct sembuf   sembuf;
3235 +
3236 +        assert(type == GSSD_CLI || type == GSSD_SVC);
3237 +
3238 +again:
3239 +        sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
3240 +        if (sem->sem_id == -1) {
3241 +                if (errno != EEXIST) {
3242 +                        printerr(0, "Create sem: %s\n", strerror(errno));
3243 +                        exit(-1);
3244 +                }
3245 +
3246 +                /* already exist. Note there's still a small window racing
3247 +                 * with other processes, due to the stupid semaphore semantics.
3248 +                 */
3249 +                sem->sem_id = semget(sem->sem_key, 0, 0700);
3250 +                if (sem->sem_id == -1) {
3251 +                        if (errno == ENOENT) {
3252 +                                printerr(0, "another instance just exit, "
3253 +                                         "try again\n");
3254 +                                goto again;
3255 +                        }
3256 +
3257 +                        printerr(0, "Obtain sem: %s\n", strerror(errno));
3258 +                        exit(-1);
3259 +                }
3260 +        } else {
3261 +                int val = 1;
3262 +
3263 +                if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
3264 +                        printerr(0, "Initialize sem: %s\n",
3265 +                                 strerror(errno));
3266 +                        exit(-1);
3267 +                }
3268 +        }
3269 +
3270 +        sembuf.sem_num = 0;
3271 +        sembuf.sem_op = -1;
3272 +        sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
3273 +
3274 +        if (semop(sem->sem_id, &sembuf, 1) != 0) {
3275 +                if (errno == EAGAIN) {
3276 +                        printerr(0, "Another instance is running, exit\n");
3277 +                        exit(0);
3278 +                }
3279 +                printerr(0, "Grab sem: %s\n", strerror(errno));
3280 +                exit(0);
3281 +        }
3282 +
3283 +        printerr(2, "Successfully created %s global identity\n", sem->name);
3284 +}
3285 +
3286 +void gssd_exit_unique(int type)
3287 +{
3288 +        assert(type == GSSD_CLI || type == GSSD_SVC);
3289 +
3290 +        /*
3291 +         * do nothing. we can't remove the sem here, otherwise the race
3292 +         * window would be much bigger. So it's sad we have to leave the
3293 +         * sem in the system forever.
3294 +         */
3295 +}
3296 +
3297 +/****************************************
3298 + * client side resolvation:             *
3299 + *    lnd/netid/nid => hostname         *
3300 + ****************************************/
3301 +
3302 +char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
3303 +
3304 +typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
3305 +                               char *buf, int buflen);
3306 +
3307 +/* FIXME what about IPv6? */
3308 +static
3309 +int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3310 +                         char *buf, int buflen)
3311 +{
3312 +        struct hostent  *ent;
3313 +
3314 +        addr = htonl(addr);
3315 +        ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
3316 +        if (!ent) {
3317 +                printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
3318 +                return -1;
3319 +        }
3320 +        if (strlen(ent->h_name) >= buflen) {
3321 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
3322 +                return -1;
3323 +        }
3324 +        strcpy(buf, ent->h_name);
3325 +
3326 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
3327 +                 lnd, net, addr, buf);
3328 +        return 0;
3329 +}
3330 +
3331 +static
3332 +int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3333 +                       char *buf, int buflen)
3334 +{
3335 +        struct utsname   uts;
3336 +        struct hostent  *ent;
3337 +
3338 +        if (addr) {
3339 +                printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
3340 +                return -1;
3341 +        }
3342 +
3343 +        if (uname(&uts)) {
3344 +                printerr(0, "%s: failed obtain local machine name\n", lnd);
3345 +                return -1;
3346 +        }
3347 +
3348 +        ent = gethostbyname(uts.nodename);
3349 +        if (!ent) {
3350 +                printerr(0, "%s: failed obtain canonical name of %s\n",
3351 +                         lnd, uts.nodename);
3352 +                return -1;
3353 +        }
3354 +
3355 +        if (strlen(ent->h_name) >= buflen) {
3356 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
3357 +                return -1;
3358 +        }
3359 +        strcpy(buf, ent->h_name);
3360 +
3361 +        printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
3362 +        return 0;
3363 +}
3364 +
3365 +static int is_space(char c)
3366 +{
3367 +        return (c == ' ' || c == '\t' || c == '\n');
3368 +}
3369 +
3370 +static
3371 +int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
3372 +                          char *namebuf, int namebuflen)
3373 +{
3374 +        const int bufsize = PATH_MAX + 256;
3375 +        char buf[bufsize], *head, *tail;
3376 +        FILE *fghn;
3377 +
3378 +        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
3379 +        printerr(2, "cmd: %s\n", buf);
3380 +
3381 +        fghn = popen(buf, "r");
3382 +        if (fghn == NULL) {
3383 +                printerr(0, "failed to call %s\n", gethostname_ex);
3384 +                return -1;
3385 +        }
3386 +
3387 +        head = fgets(buf, bufsize, fghn);
3388 +        if (head == NULL) {
3389 +                printerr(0, "can't read from %s\n", gethostname_ex);
3390 +                return -1;
3391 +        }
3392 +        if (pclose(fghn) == -1)
3393 +                printerr(1, "pclose failed, continue\n");
3394 +
3395 +        /* trim head/tail space */
3396 +        while (is_space(*head))
3397 +                head++;
3398 +
3399 +        tail = head + strlen(head);
3400 +        if (tail <= head) {
3401 +                printerr(0, "no output from %s\n", gethostname_ex);
3402 +                return -1;
3403 +        }
3404 +        while (is_space(*(tail - 1)))
3405 +                tail--;
3406 +        if (tail <= head) {
3407 +                printerr(0, "output are all space from %s\n", gethostname_ex);
3408 +                return -1;
3409 +        }
3410 +        *tail = '\0';
3411 +
3412 +        /* start with '@' means error msg */
3413 +        if (head[0] == '@') {
3414 +                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
3415 +                return -1;
3416 +        }
3417 +
3418 +        if (tail - head > namebuflen) {
3419 +                printerr(0, "external hostname too long: %s\n", head);
3420 +                return -1;
3421 +        }
3422 +
3423 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
3424 +                 lnd, net, addr, head);
3425 +        strcpy(namebuf, head);
3426 +        return 0;
3427 +}
3428 +
3429 +static struct {
3430 +        char                    *name;
3431 +        lnd_nid2hostname_t      *nid2name;
3432 +} converter[LND_ENUM_END_MARKER] = {
3433 +        {"UNUSED0",     NULL},
3434 +        [QSWLND]        = { "QSWLND",   external_nid2hostname},
3435 +        [SOCKLND]       = { "SOCKLND",  socklnd_nid2hostname },
3436 +        [GMLND]         = { "GMLND",    external_nid2hostname},
3437 +        [PTLLND]        = { "PTLLND",   external_nid2hostname },
3438 +        [O2IBLND]       = { "O2IBLND",  socklnd_nid2hostname }, /* XXX */
3439 +        [CIBLND]        = { "CIBLND",   external_nid2hostname },
3440 +        [OPENIBLND]     = { "OPENIBLND",external_nid2hostname },
3441 +        [IIBLND]        = { "IIBLND",   external_nid2hostname },
3442 +        [LOLND]         = { "LOLND",    lolnd_nid2hostname },
3443 +        [RALND]         = { "RALND",    external_nid2hostname },
3444 +        [VIBLND]        = { "VIBLND",   external_nid2hostname },
3445 +};
3446 +
3447 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
3448 +{
3449 +        uint32_t lnd, net, addr;
3450 +
3451 +        addr = LNET_NIDADDR(nid);
3452 +        net = LNET_NIDNET(nid);
3453 +        lnd = LNET_NETTYP(net);
3454 +
3455 +        if (lnd >= LND_ENUM_END_MARKER) {
3456 +                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
3457 +                return -1;
3458 +        }
3459 +
3460 +        if (converter[lnd].nid2name == NULL) {
3461 +                printerr(0, "ERROR: %s converter not ready\n",
3462 +                        converter[lnd].name);
3463 +                return -1;
3464 +        }
3465 +
3466 +        return converter[lnd].nid2name(converter[lnd].name, net, addr,
3467 +                                       buf, buflen);
3468 +}
3469 +
3470 +
3471 +/****************************************
3472 + * lnet support routine                 *
3473 + * (from lnet/libcfs/nidstrings.c       *
3474 + ****************************************/
3475 +
3476 +#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
3477 +
3478 +static int  libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
3479 +static void libcfs_ip_addr2str(uint32_t addr, char *str);
3480 +static int  libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
3481 +static void libcfs_decnum_addr2str(uint32_t addr, char *str);
3482 +static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
3483 +static int  libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
3484 +
3485 +struct netstrfns {
3486 +        int          nf_type;
3487 +        char        *nf_name;
3488 +        char        *nf_modname;
3489 +        void       (*nf_addr2str)(uint32_t addr, char *str);
3490 +        int        (*nf_str2addr)(char *str, int nob, uint32_t *addr);
3491 +};
3492 +
3493 +static struct netstrfns  libcfs_netstrfns[] = {
3494 +        {/* .nf_type      */  LOLND,
3495 +         /* .nf_name      */  "lo",
3496 +         /* .nf_modname   */  "klolnd",
3497 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
3498 +         /* .nf_str2addr  */  libcfs_lo_str2addr},
3499 +        {/* .nf_type      */  SOCKLND,
3500 +         /* .nf_name      */  "tcp",
3501 +         /* .nf_modname   */  "ksocklnd",
3502 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3503 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3504 +        {/* .nf_type      */  O2IBLND,
3505 +         /* .nf_name      */  "o2ib",
3506 +         /* .nf_modname   */  "ko2iblnd",
3507 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3508 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3509 +        {/* .nf_type      */  CIBLND,
3510 +         /* .nf_name      */  "cib",
3511 +         /* .nf_modname   */  "kciblnd",
3512 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3513 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3514 +        {/* .nf_type      */  OPENIBLND,
3515 +         /* .nf_name      */  "openib",
3516 +         /* .nf_modname   */  "kopeniblnd",
3517 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3518 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3519 +        {/* .nf_type      */  IIBLND,
3520 +         /* .nf_name      */  "iib",
3521 +         /* .nf_modname   */  "kiiblnd",
3522 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3523 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3524 +        {/* .nf_type      */  VIBLND,
3525 +         /* .nf_name      */  "vib",
3526 +         /* .nf_modname   */  "kviblnd",
3527 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3528 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3529 +        {/* .nf_type      */  RALND,
3530 +         /* .nf_name      */  "ra",
3531 +         /* .nf_modname   */  "kralnd",
3532 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
3533 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
3534 +        {/* .nf_type      */  QSWLND,
3535 +         /* .nf_name      */  "elan",
3536 +         /* .nf_modname   */  "kqswlnd",
3537 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
3538 +         /* .nf_str2addr  */  libcfs_num_str2addr},
3539 +        {/* .nf_type      */  GMLND,
3540 +         /* .nf_name      */  "gm",
3541 +         /* .nf_modname   */  "kgmlnd",
3542 +         /* .nf_addr2str  */  libcfs_hexnum_addr2str,
3543 +         /* .nf_str2addr  */  libcfs_num_str2addr},
3544 +        {/* .nf_type      */  PTLLND,
3545 +         /* .nf_name      */  "ptl",
3546 +         /* .nf_modname   */  "kptllnd",
3547 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
3548 +         /* .nf_str2addr  */  libcfs_num_str2addr},
3549 +        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
3550 +        {/* .nf_type      */  -1},
3551 +};
3552 +
3553 +const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
3554 +
3555 +static int
3556 +libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
3557 +{
3558 +        *addr = 0;
3559 +        return 1;
3560 +}
3561 +
3562 +static void
3563 +libcfs_ip_addr2str(uint32_t addr, char *str)
3564 +{
3565 +        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
3566 +                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
3567 +                 (addr >> 8) & 0xff, addr & 0xff);
3568 +}
3569 +
3570 +/* CAVEAT EMPTOR XscanfX
3571 + * I use "%n" at the end of a sscanf format to detect trailing junk.  However
3572 + * sscanf may return immediately if it sees the terminating '0' in a string, so
3573 + * I initialise the %n variable to the expected length.  If sscanf sets it;
3574 + * fine, if it doesn't, then the scan ended at the end of the string, which is
3575 + * fine too :) */
3576 +
3577 +static int
3578 +libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
3579 +{
3580 +        int   a;
3581 +        int   b;
3582 +        int   c;
3583 +        int   d;
3584 +        int   n = nob;                          /* XscanfX */
3585 +
3586 +        /* numeric IP? */
3587 +        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
3588 +            n == nob &&
3589 +            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
3590 +            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
3591 +                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
3592 +                return 1;
3593 +        }
3594 +
3595 +#ifdef HAVE_GETHOSTBYNAME
3596 +        /* known hostname? */
3597 +        if (('a' <= str[0] && str[0] <= 'z') ||
3598 +            ('A' <= str[0] && str[0] <= 'Z')) {
3599 +                char *tmp;
3600 +
3601 +                tmp = malloc(nob + 1);
3602 +                if (tmp != NULL) {
3603 +                        struct hostent *he;
3604 +
3605 +                        memcpy(tmp, str, nob);
3606 +                        tmp[nob] = 0;
3607 +
3608 +                        he = gethostbyname(tmp);
3609 +
3610 +                        free(tmp);
3611 +                        tmp = NULL;
3612 +
3613 +                        if (he != NULL) {
3614 +                                uint32_t ip = *(uint32_t *)he->h_addr;
3615 +
3616 +                                *addr = ntohl(ip);
3617 +                                return 1;
3618 +                        }
3619 +                }
3620 +        }
3621 +#endif
3622 +        return 0;
3623 +}
3624 +
3625 +static void
3626 +libcfs_decnum_addr2str(uint32_t addr, char *str)
3627 +{
3628 +        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
3629 +}
3630 +
3631 +static void
3632 +libcfs_hexnum_addr2str(uint32_t addr, char *str)
3633 +{
3634 +        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
3635 +}
3636 +
3637 +static int
3638 +libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
3639 +{
3640 +        int     n;
3641 +
3642 +        n = nob;
3643 +        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
3644 +                return 1;
3645 +
3646 +        n = nob;
3647 +        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
3648 +                return 1;
3649 +
3650 +        n = nob;
3651 +        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
3652 +                return 1;
3653 +        
3654 +        return 0;
3655 +}
3656 +
3657 +static struct netstrfns *
3658 +libcfs_lnd2netstrfns(int lnd)
3659 +{
3660 +        int    i;
3661 +
3662 +        if (lnd >= 0)
3663 +                for (i = 0; i < libcfs_nnetstrfns; i++)
3664 +                        if (lnd == libcfs_netstrfns[i].nf_type)
3665 +                                return &libcfs_netstrfns[i];
3666 +
3667 +        return NULL;
3668 +}
3669 +
3670 +static struct netstrfns *
3671 +libcfs_str2net_internal(char *str, uint32_t *net)
3672 +{
3673 +        struct netstrfns *nf;
3674 +        int               nob;
3675 +        int               netnum;
3676 +        int               i;
3677 +
3678 +        for (i = 0; i < libcfs_nnetstrfns; i++) {
3679 +                nf = &libcfs_netstrfns[i];
3680 +                if (nf->nf_type >= 0 &&
3681 +                    !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
3682 +                        break;
3683 +        }
3684 +
3685 +        if (i == libcfs_nnetstrfns)
3686 +                return NULL;
3687 +
3688 +        nob = strlen(nf->nf_name);
3689 +
3690 +        if (strlen(str) == (unsigned int)nob) {
3691 +                netnum = 0;
3692 +        } else {
3693 +                if (nf->nf_type == LOLND) /* net number not allowed */
3694 +                        return NULL;
3695 +
3696 +                str += nob;
3697 +                i = strlen(str);
3698 +                if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
3699 +                    i != (int)strlen(str))
3700 +                        return NULL;
3701 +        }
3702 +
3703 +        *net = LNET_MKNET(nf->nf_type, netnum);
3704 +        return nf;
3705 +}
3706 +
3707 +lnet_nid_t
3708 +libcfs_str2nid(char *str)
3709 +{
3710 +        char             *sep = strchr(str, '@');
3711 +        struct netstrfns *nf;
3712 +        uint32_t             net;
3713 +        uint32_t             addr;
3714 +
3715 +        if (sep != NULL) {
3716 +                nf = libcfs_str2net_internal(sep + 1, &net);
3717 +                if (nf == NULL)
3718 +                        return LNET_NID_ANY;
3719 +        } else {
3720 +                sep = str + strlen(str);
3721 +                net = LNET_MKNET(SOCKLND, 0);
3722 +                nf = libcfs_lnd2netstrfns(SOCKLND);
3723 +                if (!nf)
3724 +                        return LNET_NID_ANY;
3725 +        }
3726 +
3727 +        if (!nf->nf_str2addr(str, sep - str, &addr))
3728 +                return LNET_NID_ANY;
3729 +
3730 +        return LNET_MKNID(net, addr);
3731 +}
3732 +
3733 +/****************************************
3734 + * user mapping database handling       *
3735 + * (very rudiment)                      *
3736 + ****************************************/
3737 +
3738 +#define MAPPING_GROW_SIZE       512
3739 +#define MAX_LINE_LEN            256
3740 +
3741 +struct user_map_item {
3742 +        char        *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
3743 +        lnet_nid_t   nid;
3744 +        uid_t        uid;
3745 +};
3746 +
3747 +struct user_mapping {
3748 +        int                   nitems;
3749 +        struct user_map_item *items;
3750 +};
3751 +
3752 +static struct user_mapping mapping = {0, NULL};
3753 +/* FIXME to be finished: monitor change of mapping database */
3754 +static int mapping_mtime = 0;
3755 +
3756 +void cleanup_mapping(void)
3757 +{
3758 +        if (mapping.items) {
3759 +                for (; mapping.nitems > 0; mapping.nitems--)
3760 +                        free(mapping.items[mapping.nitems - 1].principal);
3761 +                free(mapping.items);
3762 +                mapping.items = NULL;
3763 +        }
3764 +}
3765 +
3766 +static int grow_mapping(int nitems)
3767 +{
3768 +        struct user_map_item *new;
3769 +        int oldsize, newsize;
3770 +
3771 +        oldsize = (mapping.nitems * sizeof(struct user_map_item) +
3772 +                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3773 +        newsize = (nitems * sizeof(struct user_map_item) +
3774 +                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3775 +        while (newsize <= oldsize)
3776 +                return 0;
3777 +
3778 +        newsize *= MAPPING_GROW_SIZE;
3779 +        new = malloc(newsize);
3780 +        if (!new) {
3781 +                printerr(0, "can't alloc mapping size %d\n", newsize);
3782 +                return -1;
3783 +        }
3784 +
3785 +        if (mapping.items) {
3786 +                memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
3787 +                free(mapping.items);
3788 +        }
3789 +        mapping.items = new;
3790 +        return 0;
3791 +}
3792 +
3793 +uid_t parse_uid(char *uidstr)
3794 +{
3795 +        struct passwd *pw;
3796 +        char *p = NULL;
3797 +        long uid;
3798 +
3799 +        pw = getpwnam(uidstr);
3800 +        if (pw)
3801 +                return pw->pw_uid;
3802 +
3803 +        uid = strtol(uidstr, &p, 0);
3804 +        if (*p == '\0')
3805 +                return (uid_t) uid;
3806 +
3807 +        return -1;
3808 +}
3809 +
3810 +static int read_mapping_db(void)
3811 +{
3812 +        char princ[MAX_LINE_LEN];
3813 +        char nid_str[MAX_LINE_LEN];
3814 +        char dest[MAX_LINE_LEN];
3815 +        char linebuf[MAX_LINE_LEN];
3816 +        char *line;
3817 +        lnet_nid_t nid;
3818 +        uid_t dest_uid;
3819 +        FILE *f;
3820 +
3821 +        /* cleanup old mappings */
3822 +        cleanup_mapping();
3823 +
3824 +        f = fopen(MAPPING_DATABASE_FILE, "r");
3825 +        if (!f) {
3826 +                printerr(0, "can't open mapping database: %s\n",
3827 +                         MAPPING_DATABASE_FILE);
3828 +                return -1;
3829 +        }
3830 +
3831 +        while ((line = fgets(linebuf, MAX_LINE_LEN, f)) != NULL) {
3832 +                char *name;
3833 +
3834 +                if (strlen(line) >= MAX_LINE_LEN) {
3835 +                        printerr(0, "invalid mapping db: line too long (%d)\n",
3836 +                                 strlen(line));
3837 +                        continue;
3838 +                }
3839 +
3840 +                if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
3841 +                        printerr(0, "mapping db: syntax error\n");
3842 +                        continue;
3843 +                }
3844 +
3845 +                if (!strcmp(princ, "*")) {
3846 +                        printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n");
3847 +                        continue;
3848 +                } else {
3849 +                        name = strdup(princ);
3850 +                        if (!name) {
3851 +                                printerr(0, "fail to dup str %s\n", princ);
3852 +                                continue;
3853 +                        }
3854 +                }
3855 +
3856 +                if (!strcmp(nid_str, "*")) {
3857 +                        nid = LNET_NID_ANY;
3858 +                } else {
3859 +                        nid = libcfs_str2nid(nid_str);
3860 +                        if (nid == LNET_NID_ANY) {
3861 +                                printerr(0, "fail to parse nid %s\n", nid_str);
3862 +                                free(name);
3863 +                                continue;
3864 +                        }
3865 +                }
3866 +
3867 +                dest_uid = parse_uid(dest);
3868 +                if (dest_uid == -1) {
3869 +                        printerr(0, "no valid user: %s\n", dest);
3870 +                        free(name);
3871 +                        continue;
3872 +                }
3873 +
3874 +                if (grow_mapping(mapping.nitems + 1)) {
3875 +                        printerr(0, "fail to grow mapping to %d\n",
3876 +                                 mapping.nitems + 1);
3877 +                        free(name);
3878 +                        fclose(f);
3879 +                        return -1;
3880 +                }
3881 +
3882 +                mapping.items[mapping.nitems].principal = name;
3883 +                mapping.items[mapping.nitems].nid = nid;
3884 +                mapping.items[mapping.nitems].uid = dest_uid;
3885 +                mapping.nitems++;
3886 +                printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
3887 +                         name, nid_str, nid, dest_uid);
3888 +        }
3889 +
3890 +        fclose(f);
3891 +        return 0;
3892 +}
3893 +
3894 +static inline int mapping_changed(void)
3895 +{
3896 +        struct stat st;
3897 +
3898 +        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
3899 +                /* stat failed, treat it like doesn't exist or be removed */
3900 +                if (mapping_mtime == 0) {
3901 +                        return 0;
3902 +                } else {
3903 +                        printerr(0, "Warning: stat %s failed: %s\n",
3904 +                                 MAPPING_DATABASE_FILE, strerror(errno));
3905 +
3906 +                        mapping_mtime = 0;
3907 +                        return 1;
3908 +                }
3909 +        }
3910 +
3911 +        if (st.st_mtime != mapping_mtime) {
3912 +                mapping_mtime = st.st_mtime;
3913 +                return 1;
3914 +        }
3915 +
3916 +        return 0;
3917 +}
3918 +
3919 +int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
3920 +{
3921 +        int n;
3922 +
3923 +        *uid = -1;
3924 +
3925 +        /* FIXME race condition here */
3926 +        if (mapping_changed()) {
3927 +                if (read_mapping_db())
3928 +                        printerr(0, "all remote users will be denied\n");
3929 +        }
3930 +
3931 +        for (n = 0; n < mapping.nitems; n++) {
3932 +                struct user_map_item *entry = &mapping.items[n];
3933 +
3934 +                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
3935 +                        continue;
3936 +                if (!strcasecmp(entry->principal, princ)) {
3937 +                        printerr(1, "found mapping: %s ==> %d\n",
3938 +                                 princ, entry->uid);
3939 +                        *uid = entry->uid;
3940 +                        return 0;
3941 +                }
3942 +        }
3943 +
3944 +        printerr(2, "no mapping for %s/%#Lx\n", princ, nid);
3945 +        return -1;
3946 +}
3947 diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.h nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h
3948 --- nfs-utils-1.0.10/utils/gssd/lsupport.h      1969-12-31 17:00:00.000000000 -0700
3949 +++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h       2007-05-15 13:01:35.000000000 -0600
3950 @@ -0,0 +1,85 @@
3951 +#ifndef __LIBCFS_H__
3952 +#define __LIBCFS_H__
3953 +
3954 +#include <unistd.h>
3955 +#include <stdint.h>
3956 +
3957 +#define GSSD_CLI        (0)
3958 +#define GSSD_SVC        (1)
3959 +
3960 +void gssd_init_unique(int type);
3961 +void gssd_exit_unique(int type);
3962 +
3963 +/*
3964 + * copied from lustre source
3965 + */
3966 +
3967 +#define LUSTRE_GSS_SVC_MDS      0
3968 +#define LUSTRE_GSS_SVC_OSS      1
3969 +
3970 +struct lgssd_upcall_data {
3971 +        uint32_t        seq;
3972 +        uint32_t        uid;
3973 +        uint32_t        gid;
3974 +        uint32_t        svc;
3975 +        uint64_t        nid;
3976 +        char            obd[64];
3977 +};
3978 +
3979 +#define GSSD_INTERFACE_VERSION        (1)
3980 +
3981 +struct lgssd_ioctl_param {
3982 +        int             version;        /* in   */
3983 +        char           *uuid;           /* in   */
3984 +        int             lustre_svc;     /* in   */
3985 +        uid_t           uid;            /* in   */
3986 +        gid_t           gid;            /* in   */
3987 +        long            send_token_size;/* in   */
3988 +        char           *send_token;     /* in   */
3989 +        long            reply_buf_size; /* in   */
3990 +        char           *reply_buf;      /* in   */
3991 +        long            status;         /* out  */
3992 +        long            reply_length;   /* out  */
3993 +};
3994 +
3995 +#define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
3996 +#define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
3997 +
3998 +typedef uint64_t lnet_nid_t;
3999 +typedef uint32_t lnet_netid_t;
4000 +
4001 +#define LNET_NID_ANY      ((lnet_nid_t) -1)
4002 +#define LNET_PID_ANY      ((lnet_pid_t) -1)
4003 +
4004 +enum {
4005 +        /* Only add to these values (i.e. don't ever change or redefine them):
4006 +         * network addresses depend on them... */
4007 +        QSWLND    = 1,
4008 +        SOCKLND   = 2,
4009 +        GMLND     = 3,
4010 +        PTLLND    = 4,
4011 +        O2IBLND   = 5,
4012 +        CIBLND    = 6,
4013 +        OPENIBLND = 7,
4014 +        IIBLND    = 8,
4015 +        LOLND     = 9,
4016 +        RALND     = 10,
4017 +        VIBLND    = 11,
4018 +        LND_ENUM_END_MARKER
4019 +};
4020 +
4021 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
4022 +void cleanup_mapping(void);
4023 +int lookup_mapping(char *princ, uint64_t nid, uid_t *uid);
4024 +lnet_nid_t libcfs_str2nid(char *str);
4025 +
4026 +/* how an LNET NID encodes net:address */
4027 +#define LNET_NIDADDR(nid)      ((uint32_t)((nid) & 0xffffffff))
4028 +#define LNET_NIDNET(nid)       ((uint32_t)(((nid) >> 32)) & 0xffffffff)
4029 +#define LNET_MKNID(net,addr)   ((((uint64_t)(net))<<32)|((uint64_t)(addr)))
4030 +/* how net encodes type:number */
4031 +#define LNET_NETNUM(net)       ((net) & 0xffff)
4032 +#define LNET_NETTYP(net)       (((net) >> 16) & 0xffff)
4033 +#define LNET_MKNET(typ,num)    ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
4034 +
4035 +#endif /* __LIBCFS_H__ */
4036 diff -rNup nfs-utils-1.0.10/utils/gssd/Makefile.am nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am
4037 --- nfs-utils-1.0.10/utils/gssd/Makefile.am     2007-05-15 13:02:26.000000000 -0600
4038 +++ nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am      2007-05-15 13:00:53.000000000 -0600
4039 @@ -1,17 +1,11 @@
4040  ## Process this file with automake to produce Makefile.in
4041  
4042 -man8_MANS      = gssd.man svcgssd.man
4043 -
4044 -RPCPREFIX      = rpc.
4045 +RPCPREFIX      = 
4046  KPREFIX                = @kprefix@
4047 -sbin_PREFIXED  = gssd svcgssd
4048 -sbin_PROGRAMS  = $(sbin_PREFIXED) gss_clnt_send_err
4049 +sbin_PREFIXED  = lgssd lsvcgssd
4050 +sbin_PROGRAMS  = $(sbin_PREFIXED)
4051  sbin_SCRIPTS   = gss_destroy_creds
4052  
4053 -EXTRA_DIST = \
4054 -       gss_destroy_creds \
4055 -       $(man8_MANS)
4056 -
4057  COMMON_SRCS = \
4058         context.c \
4059         context_mit.c \
4060 @@ -21,13 +15,15 @@ COMMON_SRCS = \
4061         gss_util.c \
4062         gss_oids.c \
4063         err_util.c \
4064 +       lsupport.c \
4065         \
4066         context.h \
4067         err_util.h \
4068         gss_oids.h \
4069 -       gss_util.h
4070 +       gss_util.h \
4071 +       lsupport.h
4072  
4073 -gssd_SOURCES = \
4074 +lgssd_SOURCES = \
4075         $(COMMON_SRCS) \
4076         gssd.c \
4077         gssd_main_loop.c \
4078 @@ -38,13 +34,12 @@ gssd_SOURCES = \
4079         krb5_util.h \
4080         write_bytes.h
4081  
4082 -gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
4083 -gssd_LDFLAGS = $(KRBLDFLAGS)
4084 +lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
4085 +lgssd_LDFLAGS = $(KRBLDFLAGS)
4086  
4087 -gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4088 -             $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4089 +lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
4090  
4091 -svcgssd_SOURCES = \
4092 +lsvcgssd_SOURCES = \
4093         $(COMMON_SRCS) \
4094         cacheio.c \
4095         svcgssd.c \
4096 @@ -55,20 +50,11 @@ svcgssd_SOURCES = \
4097         cacheio.h \
4098         svcgssd.h
4099  
4100 -svcgssd_LDADD = \
4101 -       ../../support/nfs/libnfs.a \
4102 -       $(RPCSECGSS_LIBS) -lnfsidmap \
4103 -       $(KRBLIBS)
4104 -
4105 -svcgssd_LDFLAGS = $(KRBLDFLAGS)
4106 -
4107 -svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4108 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4109 +lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
4110  
4111 -gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
4112 +lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
4113  
4114 -gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
4115 -                $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
4116 +lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
4117  
4118  MAINTAINERCLEANFILES = Makefile.in
4119  
4120 @@ -92,23 +78,3 @@ uninstall-hook:
4121           done)
4122  
4123  
4124 -# XXX This makes some assumptions about what automake does.
4125 -# XXX But there is no install-man-hook or install-man-local.
4126 -install-man: install-man8 install-man-links
4127 -uninstall-man: uninstall-man8 uninstall-man-links
4128 -
4129 -install-man-links:
4130 -       (cd $(DESTDIR)$(man8dir) && \
4131 -         for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
4132 -           inst=`echo $$m | sed -e 's/man$$/8/'`; \
4133 -           rm -f $(RPCPREFIX)$$inst ; \
4134 -           $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
4135 -         done)
4136 -
4137 -uninstall-man-links:
4138 -       (cd $(DESTDIR)$(man8dir) && \
4139 -         for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
4140 -           inst=`echo $$m | sed -e 's/man$$/8/'`; \
4141 -           rm -f $(RPCPREFIX)$$inst ; \
4142 -         done)
4143 -
4144 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c
4145 --- nfs-utils-1.0.10/utils/gssd/svcgssd.c       2006-08-07 00:40:50.000000000 -0600
4146 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c        2007-05-15 13:01:35.000000000 -0600
4147 @@ -43,7 +43,6 @@
4148  #include <sys/types.h>
4149  #include <sys/stat.h>
4150  #include <sys/socket.h>
4151 -#include <rpc/rpc.h>
4152  #include <fcntl.h>
4153  #include <errno.h>
4154  
4155 @@ -54,11 +53,33 @@
4156  #include <stdlib.h>
4157  #include <string.h>
4158  #include <signal.h>
4159 -#include "nfslib.h"
4160 +#include <dirent.h>
4161  #include "svcgssd.h"
4162  #include "gss_util.h"
4163  #include "err_util.h"
4164 +#include "lsupport.h"
4165  
4166 +void
4167 +closeall(int min)
4168 +{
4169 +       DIR *dir = opendir("/proc/self/fd");
4170 +       if (dir != NULL) {
4171 +               int dfd = dirfd(dir);
4172 +               struct dirent *d;
4173 +
4174 +               while ((d = readdir(dir)) != NULL) {
4175 +                       char *endp;
4176 +                       long n = strtol(d->d_name, &endp, 10);
4177 +                       if (*endp != '\0' && n >= min && n != dfd)
4178 +                               (void) close(n);
4179 +               }
4180 +               closedir(dir);
4181 +       } else {
4182 +               int fd = sysconf(_SC_OPEN_MAX);
4183 +               while (--fd >= min)
4184 +                       (void) close(fd);
4185 +       }
4186 +}
4187  /*
4188   * mydaemon creates a pipe between the partent and child
4189   * process. The parent process will wait until the
4190 @@ -139,6 +160,7 @@ void
4191  sig_die(int signal)
4192  {
4193         /* destroy krb5 machine creds */
4194 +       cleanup_mapping();
4195         printerr(1, "exiting on signal %d\n", signal);
4196         exit(1);
4197  }
4198 @@ -165,8 +187,8 @@ main(int argc, char *argv[])
4199         int get_creds = 1;
4200         int fg = 0;
4201         int verbosity = 0;
4202 -       int rpc_verbosity = 0;
4203         int opt;
4204 +       int must_srv_mds = 0, must_srv_oss = 0;
4205         extern char *optarg;
4206         char *progname;
4207  
4208 @@ -181,8 +203,13 @@ main(int argc, char *argv[])
4209                         case 'v':
4210                                 verbosity++;
4211                                 break;
4212 -                       case 'r':
4213 -                               rpc_verbosity++;
4214 +                       case 'm':
4215 +                               get_creds = 1;
4216 +                               must_srv_mds = 1;
4217 +                               break;
4218 +                       case 'o':
4219 +                               get_creds = 1;
4220 +                               must_srv_oss = 1;
4221                                 break;
4222                         default:
4223                                 usage(argv[0]);
4224 @@ -196,27 +223,18 @@ main(int argc, char *argv[])
4225                 progname = argv[0];
4226  
4227         initerr(progname, verbosity, fg);
4228 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
4229 -       authgss_set_debug_level(rpc_verbosity);
4230 -#else
4231 -       if (rpc_verbosity > 0)
4232 -               printerr(0, "Warning: rpcsec_gss library does not "
4233 -                           "support setting debug level\n");
4234 -#endif
4235  
4236         if (gssd_check_mechs() != 0) {
4237                 printerr(0, "ERROR: Problem with gssapi library\n");
4238                 exit(1);
4239         }
4240  
4241 -       if (!fg)
4242 -               mydaemon(0, 0);
4243 -
4244 -       signal(SIGINT, sig_die);
4245 -       signal(SIGTERM, sig_die);
4246 -       signal(SIGHUP, sig_hup);
4247 +       if (gssd_get_local_realm()) {
4248 +               printerr(0, "ERROR: Can't get Local Kerberos realm\n");
4249 +               exit(1);
4250 +       }
4251  
4252 -       if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
4253 +       if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
4254                  printerr(0, "unable to obtain root (machine) credentials\n");
4255                  printerr(0, "do you have a keytab entry for "
4256                             "nfs/<your.host>@<YOUR.REALM> in "
4257 @@ -225,9 +243,23 @@ main(int argc, char *argv[])
4258         }
4259  
4260         if (!fg)
4261 +               mydaemon(0, 0);
4262 +
4263 +       /*
4264 +        * XXX: There is risk of memory leak for missing call
4265 +        *      cleanup_mapping() for SIGKILL and SIGSTOP.
4266 +        */
4267 +       signal(SIGINT, sig_die);
4268 +       signal(SIGTERM, sig_die);
4269 +       signal(SIGHUP, sig_hup);
4270 +
4271 +       if (!fg)
4272                 release_parent();
4273  
4274 -       gssd_run();
4275 +       gssd_init_unique(GSSD_SVC);
4276 +
4277 +       svcgssd_run();
4278 +       cleanup_mapping();
4279         printerr(0, "gssd_run returned!\n");
4280         abort();
4281  }
4282 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.h nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h
4283 --- nfs-utils-1.0.10/utils/gssd/svcgssd.h       2006-08-07 00:40:50.000000000 -0600
4284 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h        2007-05-15 13:01:35.000000000 -0600
4285 @@ -35,9 +35,20 @@
4286  #include <sys/queue.h>
4287  #include <gssapi/gssapi.h>
4288  
4289 -void handle_nullreq(FILE *f);
4290 -void gssd_run(void);
4291 +int handle_nullreq(FILE *f);
4292 +void svcgssd_run(void);
4293 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
4294 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
4295  
4296 -#define GSSD_SERVICE_NAME      "nfs"
4297 +extern char *mds_local_realm;
4298 +extern char *oss_local_realm;
4299 +
4300 +#define GSSD_SERVICE_NAME      "lustre"
4301 +
4302 +/* XXX */
4303 +#define GSSD_SERVICE_MDS                       "lustre_mds"
4304 +#define GSSD_SERVICE_OSS                       "lustre_oss"
4305 +#define LUSTRE_ROOT_NAME                       "lustre_root"
4306 +#define LUSTRE_ROOT_NAMELEN                    11
4307  
4308  #endif /* _RPC_SVCGSSD_H_ */
4309 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c
4310 --- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c     2006-08-07 00:40:50.000000000 -0600
4311 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c      2007-05-15 13:01:35.000000000 -0600
4312 @@ -46,46 +46,66 @@
4313  #include "svcgssd.h"
4314  #include "err_util.h"
4315  
4316 +/*
4317 + * nfs4 in-kernel cache implementation make upcall failed directly
4318 + * if there's no listener detected. so here we should keep the init
4319 + * channel file open as possible as we can.
4320 + *
4321 + * unfortunately the proc doesn't support dir change notification.
4322 + * and when an entry get unlinked, we only got POLLIN event once,
4323 + * it's the only oppotunity we can close the file and startover.
4324 + */
4325  void
4326 -gssd_run()
4327 +svcgssd_run()
4328  {
4329         int                     ret;
4330 -       FILE                    *f;
4331 +       FILE                    *f = NULL;
4332         struct pollfd           pollfd;
4333 +       struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
4334  
4335 -#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
4336 +#define NULLRPC_FILE "/proc/net/rpc/auth.ptlrpcs.init/channel"
4337  
4338 -       f = fopen(NULLRPC_FILE, "rw");
4339 -
4340 -       if (!f) {
4341 -               printerr(0, "failed to open %s: %s\n",
4342 -                        NULLRPC_FILE, strerror(errno));
4343 -               exit(1);
4344 -       }
4345 -       pollfd.fd = fileno(f);
4346 -       pollfd.events = POLLIN;
4347         while (1) {
4348                 int save_err;
4349  
4350 +               while (f == NULL) {
4351 +                       f = fopen(NULLRPC_FILE, "rw");
4352 +                       if (f == NULL) {
4353 +                               printerr(4, "failed to open %s: %s\n",
4354 +                                        NULLRPC_FILE, strerror(errno));
4355 +                               nanosleep(&halfsec, NULL);
4356 +                       } else {
4357 +                               printerr(1, "successfully open %s\n",
4358 +                                        NULLRPC_FILE);
4359 +                               break;
4360 +                       }
4361 +               }
4362 +               pollfd.fd = fileno(f);
4363 +               pollfd.events = POLLIN;
4364 +
4365                 pollfd.revents = 0;
4366 -               printerr(1, "entering poll\n");
4367 -               ret = poll(&pollfd, 1, -1);
4368 +               ret = poll(&pollfd, 1, 1000);
4369                 save_err = errno;
4370 -               printerr(1, "leaving poll\n");
4371 +
4372                 if (ret < 0) {
4373 -                       if (save_err != EINTR)
4374 -                               printerr(0, "error return from poll: %s\n",
4375 -                                        strerror(save_err));
4376 +                       printerr(0, "error return from poll: %s\n",
4377 +                                strerror(save_err));
4378 +                       fclose(f);
4379 +                       f = NULL;
4380                 } else if (ret == 0) {
4381 -                       /* timeout; shouldn't happen. */
4382 +                       printerr(3, "poll timeout\n");
4383                 } else {
4384                         if (ret != 1) {
4385                                 printerr(0, "bug: unexpected poll return %d\n",
4386                                                 ret);
4387                                 exit(1);
4388                         }
4389 -                       if (pollfd.revents & POLLIN)
4390 -                               handle_nullreq(f);
4391 +                       if (pollfd.revents & POLLIN) {
4392 +                               if (handle_nullreq(f) < 0) {
4393 +                                       fclose(f);
4394 +                                       f = NULL;
4395 +                               }
4396 +                       }
4397                 }
4398         }
4399  }
4400 diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c
4401 --- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c  2006-08-07 00:40:50.000000000 -0600
4402 +++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c   2007-05-15 13:01:35.000000000 -0600
4403 @@ -35,7 +35,6 @@
4404  
4405  #include <sys/param.h>
4406  #include <sys/stat.h>
4407 -#include <rpc/rpc.h>
4408  
4409  #include <pwd.h>
4410  #include <stdio.h>
4411 @@ -44,25 +43,28 @@
4412  #include <string.h>
4413  #include <fcntl.h>
4414  #include <errno.h>
4415 -#include <nfsidmap.h>
4416 +#include <netdb.h>
4417  
4418  #include "svcgssd.h"
4419  #include "gss_util.h"
4420  #include "err_util.h"
4421  #include "context.h"
4422  #include "cacheio.h"
4423 +#include "lsupport.h"
4424  
4425  extern char * mech2file(gss_OID mech);
4426 -#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
4427 -#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.rpcsec.init/channel"
4428 +#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel"
4429 +#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.ptlrpcs.init/channel"
4430  
4431  #define TOKEN_BUF_SIZE         8192
4432  
4433  struct svc_cred {
4434 -       uid_t   cr_uid;
4435 -       gid_t   cr_gid;
4436 -       int     cr_ngroups;
4437 -       gid_t   cr_groups[NGROUPS];
4438 +       uint32_t cr_remote;
4439 +       uint32_t cr_usr_root;
4440 +       uint32_t cr_usr_mds;
4441 +       uid_t    cr_uid;
4442 +       uid_t    cr_mapped_uid;
4443 +       uid_t    cr_gid;
4444  };
4445  
4446  static int
4447 @@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han
4448                 gss_OID mech, gss_buffer_desc *context_token)
4449  {
4450         FILE *f;
4451 -       int i;
4452         char *fname = NULL;
4453  
4454 -       printerr(1, "doing downcall\n");
4455 +       printerr(2, "doing downcall\n");
4456         if ((fname = mech2file(mech)) == NULL)
4457                 goto out_err;
4458         f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
4459 @@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han
4460         qword_printhex(f, out_handle->value, out_handle->length);
4461         /* XXX are types OK for the rest of this? */
4462         qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
4463 +       qword_printint(f, cred->cr_remote);
4464 +       qword_printint(f, cred->cr_usr_root);
4465 +       qword_printint(f, cred->cr_usr_mds);
4466 +       qword_printint(f, cred->cr_mapped_uid);
4467         qword_printint(f, cred->cr_uid);
4468         qword_printint(f, cred->cr_gid);
4469 -       qword_printint(f, cred->cr_ngroups);
4470 -       for (i=0; i < cred->cr_ngroups; i++)
4471 -               qword_printint(f, cred->cr_groups[i]);
4472         qword_print(f, fname);
4473         qword_printhex(f, context_token->value, context_token->length);
4474         qword_eol(f);
4475 @@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc *
4476         /* XXXARG: */
4477         int g;
4478  
4479 -       printerr(1, "sending null reply\n");
4480 +       printerr(2, "sending null reply\n");
4481  
4482         qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
4483         qword_addhex(&bp, &blen, in_token->value, in_token->length);
4484 @@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc *
4485  #define rpcsec_gsserr_credproblem      13
4486  #define rpcsec_gsserr_ctxproblem       14
4487  
4488 +#if 0
4489  static void
4490  add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
4491  {
4492 @@ -182,7 +185,9 @@ add_supplementary_groups(char *secname, 
4493                 }
4494         }
4495  }
4496 +#endif
4497  
4498 +#if 0
4499  static int
4500  get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
4501  {
4502 @@ -248,7 +253,9 @@ out_free:
4503  out:
4504         return res;
4505  }
4506 +#endif
4507  
4508 +#if 0
4509  void
4510  print_hexl(int pri, unsigned char *cp, int length)
4511  {
4512 @@ -285,12 +292,121 @@ print_hexl(int pri, unsigned char *cp, i
4513                 printerr(pri,"\n");
4514         }
4515  }
4516 +#endif
4517  
4518 -void
4519 +static int
4520 +get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
4521 +       lnet_nid_t nid, uint32_t lustre_svc)
4522 +{
4523 +       u_int32_t       maj_stat, min_stat;
4524 +       gss_buffer_desc name;
4525 +       char            *sname, *realm, *slash;
4526 +       int             res = -1;
4527 +       gss_OID         name_type = GSS_C_NO_OID;
4528 +       struct passwd   *pw;
4529 +
4530 +       cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
4531 +       cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
4532 +
4533 +       maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
4534 +       if (maj_stat != GSS_S_COMPLETE) {
4535 +               pgsserr("get_ids: gss_display_name",
4536 +                       maj_stat, min_stat, mech);
4537 +               return -1;
4538 +       }
4539 +       if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
4540 +           !(sname = calloc(name.length + 1, 1))) {
4541 +               printerr(0, "WARNING: get_ids: error allocating %d bytes "
4542 +                       "for sname\n", name.length + 1);
4543 +               gss_release_buffer(&min_stat, &name);
4544 +               return -1;
4545 +       }
4546 +       memcpy(sname, name.value, name.length);
4547 +       printerr(1, "authenticated %s from %016llx\n", sname, nid);
4548 +       gss_release_buffer(&min_stat, &name);
4549 +
4550 +       if (lustre_svc == LUSTRE_GSS_SVC_MDS)
4551 +               lookup_mapping(sname, nid, &cred->cr_mapped_uid);
4552 +       else
4553 +               cred->cr_mapped_uid = -1;
4554 +
4555 +        realm = strchr(sname, '@');
4556 +        if (!realm) {
4557 +                printerr(0, "WARNNING: principal %s contains no realm name\n",
4558 +                        sname);
4559 +                cred->cr_remote = (mds_local_realm != NULL);
4560 +        } else {
4561 +                *realm++ = '\0';
4562 +                if (!mds_local_realm)
4563 +                        cred->cr_remote = 1;
4564 +                else
4565 +                        cred->cr_remote =
4566 +                                (strcasecmp(mds_local_realm, realm) != 0);
4567 +        }
4568 +
4569 +        if (cred->cr_remote) {
4570 +                if (cred->cr_mapped_uid != -1)
4571 +                        res = 0;
4572 +               else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
4573 +                        strcmp(sname, "lustre_root") == 0)
4574 +                        res = 0;
4575 +                else
4576 +                        printerr(0, "principal %s is remote without mapping\n",
4577 +                                 sname);
4578 +               goto out_free;
4579 +        }
4580 +
4581 +        slash = strchr(sname, '/');
4582 +        if (slash)
4583 +                *slash = '\0';
4584 +
4585 +        if (!(pw = getpwnam(sname))) {
4586 +                /* If client use machine credential, we map it to root, which
4587 +                 * will subject to further mapping by root-squash in kernel.
4588 +                 *
4589 +                 * MDS service keytab is treated as special user, also mapped
4590 +                 * to root. OSS service keytab can't be used as a user.
4591 +                 */
4592 +                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
4593 +                        printerr(2, "lustre_root principal, resolve to uid 0\n");
4594 +                        cred->cr_uid = 0;
4595 +                        cred->cr_usr_root = 1;
4596 +                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
4597 +                        printerr(2, "mds service principal, resolve to uid 0\n");
4598 +                        cred->cr_uid = 0;
4599 +                        cred->cr_usr_mds = 1;
4600 +                } else {
4601 +                        cred->cr_uid = -1;
4602 +                        if (cred->cr_mapped_uid == -1) {
4603 +                                printerr(0, "invalid user %s\n", sname);
4604 +                                goto out_free;
4605 +                        }
4606 +                        printerr(2, "user %s mapped to %u\n",
4607 +                                 sname, cred->cr_mapped_uid);
4608 +                }
4609 +        } else {
4610 +                cred->cr_uid = pw->pw_uid;
4611 +                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
4612 +        }
4613 +
4614 +        res = 0;
4615 +out_free:
4616 +        free(sname);
4617 +        return res;
4618 +}
4619 +
4620 +typedef struct gss_union_ctx_id_t {
4621 +       gss_OID         mech_type;
4622 +       gss_ctx_id_t    internal_ctx_id;
4623 +} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
4624 +
4625 +/*
4626 + * return -1 only if we detect error during reading from upcall channel,
4627 + * all other cases return 0.
4628 + */
4629 +int
4630  handle_nullreq(FILE *f) {
4631 -       /* XXX initialize to a random integer to reduce chances of unnecessary
4632 -        * invalidation of existing ctx's on restarting svcgssd. */
4633 -       static u_int32_t        handle_seq = 0;
4634 +       uint64_t                handle_seq;
4635         char                    in_tok_buf[TOKEN_BUF_SIZE];
4636         char                    in_handle_buf[15];
4637         char                    out_handle_buf[15];
4638 @@ -302,10 +418,13 @@ handle_nullreq(FILE *f) {
4639                                 ignore_out_tok = {.value = NULL},
4640         /* XXX isn't there a define for this?: */
4641                                 null_token = {.value = NULL};
4642 +       uint32_t                lustre_svc;
4643 +       lnet_nid_t              nid;
4644         u_int32_t               ret_flags;
4645         gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
4646         gss_name_t              client_name;
4647         gss_OID                 mech = GSS_C_NO_OID;
4648 +       gss_cred_id_t           svc_cred;
4649         u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
4650         u_int32_t               ignore_min_stat;
4651         struct svc_cred         cred;
4652 @@ -313,25 +432,31 @@ handle_nullreq(FILE *f) {
4653         static int              lbuflen = 0;
4654         static char             *cp;
4655  
4656 -       printerr(1, "handling null request\n");
4657 +       printerr(2, "handling null request\n");
4658  
4659         if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
4660                 printerr(0, "WARNING: handle_nullreq: "
4661                             "failed reading request\n");
4662 -               return;
4663 +               return -1;
4664         }
4665  
4666         cp = lbuf;
4667  
4668 +       qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
4669 +       qword_get(&cp, (char *) &nid, sizeof(nid));
4670 +       qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
4671 +       printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
4672 +                lustre_svc, nid, handle_seq);
4673 +
4674         in_handle.length = (size_t) qword_get(&cp, in_handle.value,
4675                                               sizeof(in_handle_buf));
4676 -       printerr(2, "in_handle: \n");
4677 -       print_hexl(2, in_handle.value, in_handle.length);
4678 +       printerr(3, "in_handle: \n");
4679 +       print_hexl(3, in_handle.value, in_handle.length);
4680  
4681         in_tok.length = (size_t) qword_get(&cp, in_tok.value,
4682                                            sizeof(in_tok_buf));
4683 -       printerr(2, "in_tok: \n");
4684 -       print_hexl(2, in_tok.value, in_tok.length);
4685 +       printerr(3, "in_tok: \n");
4686 +       print_hexl(3, in_tok.value, in_tok.length);
4687  
4688         if (in_tok.length < 0) {
4689                 printerr(0, "WARNING: handle_nullreq: "
4690 @@ -351,7 +476,13 @@ handle_nullreq(FILE *f) {
4691                 memcpy(&ctx, in_handle.value, in_handle.length);
4692         }
4693  
4694 -       maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
4695 +       svc_cred = gssd_select_svc_cred(lustre_svc);
4696 +       if (!svc_cred) {
4697 +               printerr(0, "no service credential for svc %u\n", lustre_svc);
4698 +               goto out_err;
4699 +       }
4700 +
4701 +       maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
4702                         &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
4703                         &mech, &out_tok, &ret_flags, NULL, NULL);
4704  
4705 @@ -369,7 +500,8 @@ handle_nullreq(FILE *f) {
4706                         maj_stat, min_stat, mech);
4707                 goto out_err;
4708         }
4709 -       if (get_ids(client_name, mech, &cred)) {
4710 +
4711 +       if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
4712                 /* get_ids() prints error msg */
4713                 maj_stat = GSS_S_BAD_NAME; /* XXX ? */
4714                 gss_release_name(&ignore_min_stat, &client_name);
4715 @@ -377,10 +509,8 @@ handle_nullreq(FILE *f) {
4716         }
4717         gss_release_name(&ignore_min_stat, &client_name);
4718  
4719 -
4720         /* Context complete. Pass handle_seq in out_handle to use
4721          * for context lookup in the kernel. */
4722 -       handle_seq++;
4723         out_handle.length = sizeof(handle_seq);
4724         memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
4725  
4726 @@ -404,8 +534,7 @@ out:
4727                 free(ctx_token.value);
4728         if (out_tok.value != NULL)
4729                 gss_release_buffer(&ignore_min_stat, &out_tok);
4730 -       printerr(1, "finished handling null request\n");
4731 -       return;
4732 +       return 0;
4733  
4734  out_err:
4735         if (ctx != GSS_C_NO_CONTEXT)
4736 diff -rNup nfs-utils-1.0.10/utils/Makefile.am nfs-utils-1.0.10.lustre/utils/Makefile.am
4737 --- nfs-utils-1.0.10/utils/Makefile.am  2006-08-07 00:40:50.000000000 -0600
4738 +++ nfs-utils-1.0.10.lustre/utils/Makefile.am   2007-05-15 13:00:53.000000000 -0600
4739 @@ -2,31 +2,6 @@
4740  
4741  OPTDIRS =
4742  
4743 -if CONFIG_RQUOTAD
4744 -OPTDIRS += rquotad
4745 -endif
4746 -
4747 -if CONFIG_NFSV4
4748 -OPTDIRS += idmapd
4749 -endif
4750 -
4751 -if CONFIG_GSS
4752 -OPTDIRS += gssd
4753 -endif
4754 -
4755 -if CONFIG_MOUNT
4756 -OPTDIRS += mount
4757 -endif
4758 -
4759 -SUBDIRS = \
4760 -       exportfs \
4761 -       lockd \
4762 -       mountd \
4763 -       nfsd \
4764 -       nfsstat \
4765 -       nhfsstone \
4766 -       showmount \
4767 -       statd \
4768 -       $(OPTDIRS)
4769 +SUBDIRS = gssd
4770  
4771  MAINTAINERCLEANFILES = Makefile.in