Whamcloud - gitweb
LU-9679 general: add missing spaces to folded strings.
[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 + ****************************************/