]> git.pld-linux.org Git - packages/nfs-utils.git/blob - nfs-utils-CITI_NFS4.patch
- started update to 1.1.0-rc1
[packages/nfs-utils.git] / nfs-utils-CITI_NFS4.patch
1
2
3 The complete set of CITI nfs-utils patches rolled into one patch.
4
5 Changes since 1.0.10-CITI_NFS4_ALL-4:
6
7  * Update to nfs-utils-1.0.11
8
9  * Include missing fslocations files and a small change so that
10    fslocations works.
11
12  * Include several mount patches from Steve Dickson
13
14  * Add a patch to put the mount.nfs[4] and umount.nfs[4] in the
15    place where mount expects them during install.
16
17
18 ---
19
20  nfs-utils-1.0.11-kwc/Makefile.in                        |  136 
21  nfs-utils-1.0.11-kwc/aclocal.m4                         |  250 
22  nfs-utils-1.0.11-kwc/configure                          | 4436 +++++++++++-----
23  nfs-utils-1.0.11-kwc/linux-nfs/Makefile.in              |   88 
24  nfs-utils-1.0.11-kwc/support/Makefile.in                |  120 
25  nfs-utils-1.0.11-kwc/support/export/Makefile.in         |  113 
26  nfs-utils-1.0.11-kwc/support/export/export.c            |    2 
27  nfs-utils-1.0.11-kwc/support/include/Makefile.in        |  124 
28  nfs-utils-1.0.11-kwc/support/include/fstab.h            |    8 
29  nfs-utils-1.0.11-kwc/support/include/nfs/Makefile.in    |   88 
30  nfs-utils-1.0.11-kwc/support/include/nfs_mntent.h       |    8 
31  nfs-utils-1.0.11-kwc/support/include/nfslib.h           |    6 
32  nfs-utils-1.0.11-kwc/support/include/rpcsvc/Makefile.in |   88 
33  nfs-utils-1.0.11-kwc/support/include/sys/Makefile.in    |  120 
34  nfs-utils-1.0.11-kwc/support/include/sys/fs/Makefile.in |   88 
35  nfs-utils-1.0.11-kwc/support/misc/Makefile.in           |  113 
36  nfs-utils-1.0.11-kwc/support/nfs/Makefile.in            |  113 
37  nfs-utils-1.0.11-kwc/support/nfs/conn.c                 |    2 
38  nfs-utils-1.0.11-kwc/support/nfs/exports.c              |  149 
39  nfs-utils-1.0.11-kwc/support/nfs/fstab.c                |   57 
40  nfs-utils-1.0.11-kwc/tools/Makefile.in                  |  120 
41  nfs-utils-1.0.11-kwc/tools/getiversion/Makefile.in      |  126 
42  nfs-utils-1.0.11-kwc/tools/locktest/Makefile.in         |  126 
43  nfs-utils-1.0.11-kwc/tools/nlmtest/Makefile.in          |   88 
44  nfs-utils-1.0.11-kwc/tools/rpcdebug/Makefile.in         |  135 
45  nfs-utils-1.0.11-kwc/tools/rpcgen/Makefile.in           |  198 
46  nfs-utils-1.0.11-kwc/utils/Makefile.in                  |  120 
47  nfs-utils-1.0.11-kwc/utils/exportfs/Makefile.in         |  130 
48  nfs-utils-1.0.11-kwc/utils/exportfs/exportfs.c          |    5 
49  nfs-utils-1.0.11-kwc/utils/exportfs/exports.man         |   14 
50  nfs-utils-1.0.11-kwc/utils/gssd/Makefile.in             |  356 -
51  nfs-utils-1.0.11-kwc/utils/gssd/context.h               |    6 
52  nfs-utils-1.0.11-kwc/utils/gssd/context_lucid.c         |  391 +
53  nfs-utils-1.0.11-kwc/utils/gssd/context_mit.c           |  256 
54  nfs-utils-1.0.11-kwc/utils/gssd/gssd.c                  |   17 
55  nfs-utils-1.0.11-kwc/utils/gssd/gssd.h                  |    3 
56  nfs-utils-1.0.11-kwc/utils/gssd/gssd_main_loop.c        |    4 
57  nfs-utils-1.0.11-kwc/utils/gssd/gssd_proc.c             |   22 
58  nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.c             |  228 
59  nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.h             |    2 
60  nfs-utils-1.0.11-kwc/utils/idmapd/Makefile.in           |  124 
61  nfs-utils-1.0.11-kwc/utils/lockd/Makefile.in            |  126 
62  nfs-utils-1.0.11-kwc/utils/mount/Makefile.am            |   15 
63  nfs-utils-1.0.11-kwc/utils/mount/Makefile.in            |  140 
64  nfs-utils-1.0.11-kwc/utils/mount/mount.c                |  211 
65  nfs-utils-1.0.11-kwc/utils/mount/nfs4mount.c            |    3 
66  nfs-utils-1.0.11-kwc/utils/mount/nfs_mount.h            |    4 
67  nfs-utils-1.0.11-kwc/utils/mount/nfsmount.c             |   70 
68  nfs-utils-1.0.11-kwc/utils/mount/nfsumount.c            |   53 
69  nfs-utils-1.0.11-kwc/utils/mountd/Makefile.in           |  182 
70  nfs-utils-1.0.11-kwc/utils/mountd/cache.c               |   16 
71  nfs-utils-1.0.11-kwc/utils/mountd/fsloc.c               |  188 
72  nfs-utils-1.0.11-kwc/utils/mountd/fsloc.h               |   50 
73  nfs-utils-1.0.11-kwc/utils/nfsd/Makefile.in             |  126 
74  nfs-utils-1.0.11-kwc/utils/nfsstat/Makefile.in          |  124 
75  nfs-utils-1.0.11-kwc/utils/rquotad/Makefile.in          |  166 
76  nfs-utils-1.0.11-kwc/utils/showmount/Makefile.in        |  132 
77  nfs-utils-1.0.11-kwc/utils/statd/Makefile.in            |  126 
78  58 files changed, 6974 insertions(+), 3338 deletions(-)
79
80 --- nfs-utils-1.0.12/utils/mountd/cache.c.orig  2007-02-27 05:55:40.000000000 +0100
81 +++ nfs-utils-1.0.12/utils/mountd/cache.c       2007-03-11 00:38:34.746218136 +0100
82 @@ -445,6 +445,19 @@
83         release_replicas(servers);
84  }
85  
86 +static void write_secinfo(FILE *f, struct exportent *ep)
87 +{
88 +       int *p;
89 +       qword_print(f, "secinfo");
90 +       for (p=ep->e_secinfo_order; *p>=0; p++)
91 +               ; /* Do nothing */
92 +       qword_printint(f, p - ep->e_secinfo_order);
93 +       for (p=ep->e_secinfo_order; *p>=0; p++) {
94 +               qword_print(f, secflavor_name[*p]);
95 +               qword_printint(f, ep->e_secinfo_flags[*p]);
96 +       }
97 +}
98 +
99  static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
100  {
101         qword_print(f, domain);
102 @@ -466,6 +479,7 @@
103                         qword_print(f, "uuid");
104                         qword_printhex(f, exp->e_uuid, 16);
105                 }
106 +               write_secinfo(f, exp);
107         }
108         return qword_eol(f);
109  }
110 --- nfs-utils-1.0.12/support/nfs/exports.c.orig 2007-02-27 05:55:40.000000000 +0100
111 +++ nfs-utils-1.0.12/support/nfs/exports.c      2007-03-11 00:39:09.496198423 +0100
112 @@ -51,6 +51,10 @@
113  static int     parsemaptype(char *type);
114  static void    freesquash(void);
115  static void    syntaxerr(char *msg);
116 +static unsigned int parse_flavors(char *str, struct exportent *ep);
117 +static int     secinfo_default(struct exportent *ep);
118 +static void    setflags(int mask, unsigned int *ap, struct exportent *ep);
119 +static void    clearflags(int mask, unsigned int *ap, struct exportent *ep);
120  
121  void
122  setexportent(char *fname, char *type)
123 @@ -102,6 +106,7 @@
124                 def_ee.e_mountpoint = NULL;
125                 def_ee.e_fslocmethod = FSLOC_NONE;
126                 def_ee.e_fslocdata = NULL;
127 +               def_ee.e_secinfo_order[0] = -1;
128                 def_ee.e_nsquids = 0;
129                 def_ee.e_nsqgids = 0;
130  
131 @@ -182,6 +187,19 @@
132  }
133  
134  void
135 +secinfo_show(FILE *fp, struct exportent *ep)
136 +{
137 +       int *p1, *p2;
138 +       for (p1=ep->e_secinfo_order; *p1>=0; p1=p2) {
139 +               fprintf(fp, ",sec=%s", secflavor_name[*p1]);
140 +               for (p2=p1+1; (*p2>=0) && (ep->e_secinfo_flags[*p1]==ep->e_secinfo_flags[*p2]); p2++) {
141 +                       fprintf(fp, ":%s", secflavor_name[*p2]);
142 +               }
143 +               fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw");
144 +       }
145 +}
146 +
147 +void
148  putexportent(struct exportent *ep)
149  {
150         FILE    *fp;
151 @@ -199,7 +217,6 @@
152                         fprintf(fp, "%c", esc[i]);
153  
154         fprintf(fp, "\t%s(", ep->e_hostname);
155 -       fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
156         fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
157         fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
158                                 "" : "no_");
159 @@ -276,7 +293,9 @@
160                         else
161                                 fprintf(fp, "%d,", id[i]);
162         }
163 -       fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid);
164 +       fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
165 +       secinfo_show(fp, ep);
166 +       fprintf(fp, ")\n");
167  }
168  
169  void
170 @@ -325,6 +344,7 @@
171         ee.e_mountpoint = NULL;
172         ee.e_fslocmethod = FSLOC_NONE;
173         ee.e_fslocdata = NULL;
174 +       ee.e_secinfo_order[0] = -1;
175         ee.e_nsquids = 0;
176         ee.e_nsqgids = 0;
177         ee.e_uuid = NULL;
178 @@ -376,6 +396,9 @@
179         int     had_subtree_opt = 0;
180         char    *flname = efname?efname:"command line";
181         int     flline = efp?efp->x_line:0;
182 +       int     *p;
183 +       unsigned int active = 0;
184 +       int secmask = NFSEXP_READONLY;  /* options that can vary per flavor */
185  
186         squids = ep->e_squids; nsquids = ep->e_nsquids;
187         sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
188 @@ -398,9 +421,9 @@
189  
190                 /* process keyword */
191                 if (strcmp(opt, "ro") == 0)
192 -                       ep->e_flags |= NFSEXP_READONLY;
193 +                       setflags(NFSEXP_READONLY, &active, ep);
194                 else if (strcmp(opt, "rw") == 0)
195 -                       ep->e_flags &= ~NFSEXP_READONLY;
196 +                       clearflags(NFSEXP_READONLY, &active, ep);
197                 else if (!strcmp(opt, "secure"))
198                         ep->e_flags &= ~NFSEXP_INSECURE_PORT;
199                 else if (!strcmp(opt, "insecure"))
200 @@ -522,6 +545,10 @@
201                 } else if (strncmp(opt, "replicas=", 9) == 0) {
202                         ep->e_fslocmethod = FSLOC_REPLICA;
203                         ep->e_fslocdata = strdup(opt+9);
204 +               } else if (strncmp(opt, "sec=", 4) == 0) {
205 +                       active = parse_flavors(opt+4, ep);
206 +                       if (!active)
207 +                               goto bad_option;
208                 } else {
209                         xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
210                                         flname, flline, opt);
211 @@ -533,6 +560,12 @@
212                         cp++;
213         }
214  
215 +       if (!active)
216 +               active = secinfo_default(ep);
217 +       for (p=ep->e_secinfo_order; *p>=0; p++)
218 +               ep->e_secinfo_flags[*p] |= (ep->e_flags & ~secmask);
219 +       /* If did not use sec= option, ensure e_flags is backward compatible */
220 +       ep->e_flags = ep->e_secinfo_flags[ep->e_secinfo_order[0]];
221         ep->e_squids = squids;
222         ep->e_sqgids = sqgids;
223         ep->e_nsquids = nsquids;
224 @@ -663,3 +696,107 @@
225                         efname, efp?efp->x_line:0, msg);
226  }
227  
228 +char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
229 +                                         "krb5",
230 +                                         "krb5i",
231 +                                         "krb5p",
232 +                                         "spkm3",
233 +                                         "spkm3i",
234 +                                         "spkm3p"
235 +};
236 +
237 +static void
238 +secinfo_addflavor(int bit, struct exportent *ep)
239 +{
240 +       int *p;
241 +       for (p=ep->e_secinfo_order; *p>=0; p++) {
242 +               if (*p == bit)
243 +                       return;
244 +       }
245 +       *p++ = bit;
246 +       *p = -1;
247 +       ep->e_secinfo_flags[bit] = 0;
248 +}
249 +
250 +static int
251 +secinfo_nameindex(char *name)
252 +{
253 +       int i;
254 +       for (i=0; i<SECFLAVOR_COUNT; i++) {
255 +               if (strcmp(secflavor_name[i], name) == 0)
256 +                       return i;
257 +       }
258 +       return -1;
259 +}
260 +
261 +/* @str is a colon seperated list of security flavors.  Their order
262 + * is recorded in @ep, and a bitmap corresponding to the list is returned.
263 + * A zero return indicates an error.
264 + */
265 +static unsigned int
266 +parse_flavors(char *str, struct exportent *ep)
267 +{
268 +       unsigned int out=0;
269 +       char *flavor;
270 +       int bit; 
271 +
272 +       while ( (flavor=strsep(&str, ":")) ) {
273 +               bit = secinfo_nameindex(flavor);
274 +               if (bit == -1) {
275 +                       xlog(L_ERROR, "unknown flavor %s\n", flavor);
276 +                       return 0;
277 +               }
278 +               out |= 1<<bit;
279 +               secinfo_addflavor(bit, ep);
280 +       }
281 +       return out;
282 +}
283 +
284 +/* Determine a default security flavor based on ep->e_hostname. */
285 +static int
286 +secinfo_default(struct exportent *ep)
287 +{
288 +       int i=-1;
289 +       if (strncmp(ep->e_hostname, "gss/", 4) == 0) {
290 +               i = secinfo_nameindex(ep->e_hostname + 4);
291 +               if (i < 0)
292 +                       xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname);
293 +       }
294 +       /* Default to auth_sys */
295 +       if (i < 0)
296 +               i = secinfo_nameindex("sys");
297 +       secinfo_addflavor(i, ep);
298 +       return 1<<i;
299 +}
300 +
301 +/* Sets the bits in @mask for the appropriate security flavor flags. */
302 +static void
303 +setflags(int mask, unsigned int *ap, struct exportent *ep)
304 +{
305 +       int active, flavor=0;
306 +       if (!*ap)
307 +               *ap = secinfo_default(ep);
308 +       active = *ap;
309 +       while (active) {
310 +               if (active & 1)
311 +                       ep->e_secinfo_flags[flavor] |= mask;
312 +               flavor++;
313 +               active >>= 1;
314 +       }
315 +}
316 +
317 +/* Clears the bits in @mask for the appropriate security flavor flags. */
318 +static void
319 +clearflags(int mask, unsigned int *ap, struct exportent *ep)
320 +{
321 +       int active, flavor=0;
322 +       if (!*ap)
323 +               *ap = secinfo_default(ep);
324 +       active = *ap;
325 +       while (active) {
326 +               if (active & 1)
327 +                       ep->e_secinfo_flags[flavor] &= ~mask;
328 +               flavor++;
329 +               active >>= 1;
330 +       }
331 +}
332 --- nfs-utils-1.0.12/utils/exportfs/exportfs.c.orig     2007-02-27 05:55:40.000000000 +0100
333 +++ nfs-utils-1.0.12/utils/exportfs/exportfs.c  2007-03-11 00:39:30.569399317 +0100
334 @@ -376,10 +376,12 @@
335                                 continue;
336                         }
337                         c = '(';
338 +                       /*
339                         if (ep->e_flags & NFSEXP_READONLY)
340                                 c = dumpopt(c, "ro");
341                         else
342                                 c = dumpopt(c, "rw");
343 +                       */
344                         if (ep->e_flags & NFSEXP_ASYNC)
345                                 c = dumpopt(c, "async");
346                         if (ep->e_flags & NFSEXP_GATHERED_WRITES)
347 @@ -433,6 +435,7 @@
348                                 break;
349  #endif
350                         }
351 +                       secinfo_show(stdout, ep);
352                         printf("%c\n", (c != '(')? ')' : ' ');
353                 }
354         }
355 diff -puN utils/exportfs/exports.man~CITI_NFS4_ALL utils/exportfs/exports.man
356 --- nfs-utils-1.0.11/utils/exportfs/exports.man~CITI_NFS4_ALL   2007-02-26 18:52:07.928367000 -0500
357 +++ nfs-utils-1.0.11-kwc/utils/exportfs/exports.man     2007-02-26 18:52:08.691050000 -0500
358 @@ -348,6 +348,20 @@ If the client asks for alternative locat
359  will be given this list of alternatives. (Note that actual replication
360  of the filesystem must be handled elsewhere.)
361  
362 +.TP
363 +.IR refer= path@host[+host][:path@host[+host]]
364 +A client referencing the export point will be directed to choose from
365 +the given list an alternative location for the filesystem.
366 +(Note that the server must have a mountpoint here, though a different
367 +filesystem is not required; so, for example,
368 +.IR "mount --bind" " /path /path"
369 +is sufficient.)
370 +.TP
371 +.IR replicas= path@host[+host][:path@host[+host]]
372 +If the client asks for alternative locations for the export point, it
373 +will be given this list of alternatives. (Note that actual replication
374 +of the filesystem must be handled elsewhere.)
375 +
376  .SS User ID Mapping
377  .PP
378  .I nfsd
379 diff -puN /dev/null utils/mountd/fsloc.c
380 --- /dev/null   2007-02-26 18:43:11.800773059 -0500
381 +++ nfs-utils-1.0.11-kwc/utils/mountd/fsloc.c   2007-02-26 18:52:08.724017000 -0500
382 @@ -0,0 +1,188 @@
383 +/*
384 + * COPYRIGHT (c) 2006
385 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
386 + * ALL RIGHTS RESERVED
387 + *
388 + * Permission is granted to use, copy, create derivative works
389 + * and redistribute this software and such derivative works
390 + * for any purpose, so long as the name of The University of
391 + * Michigan is not used in any advertising or publicity
392 + * pertaining to the use of distribution of this software
393 + * without specific, written prior authorization.  If the
394 + * above copyright notice or any other identification of the
395 + * University of Michigan is included in any copy of any
396 + * portion of this software, then the disclaimer below must
397 + * also be included.
398 + *
399 + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
400 + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
401 + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
402 + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
403 + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
404 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
405 + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
406 + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
407 + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
408 + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
409 + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
410 + * SUCH DAMAGES.
411 + */
412 +
413 +#include <stdlib.h>
414 +#include <string.h>
415 +#include <syslog.h>
416 +
417 +#include "fsloc.h"
418 +#include "exportfs.h"
419 +
420 +/* Debugging tool: prints out @servers info to syslog */
421 +static void replicas_print(struct servers *sp)
422 +{
423 +       int i;
424 +       if (!sp) {
425 +               xlog(L_NOTICE, "NULL replicas pointer\n");
426 +               return;
427 +       }
428 +       xlog(L_NOTICE, "replicas listsize=%i\n", sp->h_num);
429 +       for (i=0; i<sp->h_num; i++) {
430 +               xlog(L_NOTICE, "    %s:%s\n",
431 +                      sp->h_mp[i]->h_host, sp->h_mp[i]->h_path);
432 +       }
433 +}
434 +
435 +#ifdef DEBUG
436 +/* Called by setting 'Method = stub' in config file.  Just returns
437 + * some syntactically correct gibberish for testing purposes.
438 + */
439 +static struct servers *method_stub(char *key)
440 +{
441 +       struct servers *sp;
442 +       struct mount_point *mp;
443 +
444 +       xlog(L_NOTICE, "called method_stub\n");
445 +       sp = malloc(sizeof(struct servers));
446 +       if (!sp)
447 +               return NULL;
448 +       mp = calloc(1, sizeof(struct mount_point));
449 +       if (!mp) {
450 +               free(sp);
451 +               return NULL;
452 +       }
453 +       sp->h_num = 1;
454 +       sp->h_mp[0] = mp;
455 +       mp->h_host = strdup("stub_server");
456 +       mp->h_path = strdup("/my/test/path");
457 +       sp->h_referral = 1;
458 +       return sp;
459 +}
460 +#endif /* DEBUG */
461 +
462 +/* Scan @list, which is a NULL-terminated array of strings of the
463 + * form path@host[+host], and return corresponding servers structure.
464 + */
465 +static struct servers *parse_list(char **list)
466 +{
467 +       int i;
468 +       struct servers *res;
469 +       struct mount_point *mp;
470 +       char *cp;
471 +
472 +       res = malloc(sizeof(struct servers));
473 +       if (!res)
474 +               return NULL;
475 +       res->h_num = 0;
476 +
477 +       /* parse each of the answers in sucession. */
478 +       for (i=0; list[i] && i<FSLOC_MAX_LIST; i++) {
479 +               mp = calloc(1, sizeof(struct mount_point));
480 +               if (!mp) {
481 +                       release_replicas(res);
482 +                       return NULL;
483 +               }
484 +               cp = strchr(list[i], '@');
485 +               if ((!cp) || list[i][0] != '/') {
486 +                       xlog(L_WARNING, "invalid entry '%s'", list[i]);
487 +                       continue; /* XXX Need better error handling */
488 +               }
489 +               res->h_mp[i] = mp;
490 +               res->h_num++;
491 +               mp->h_path = strndup(list[i], cp - list[i]);
492 +               cp++;
493 +               mp->h_host = strdup(cp);
494 +               /* hosts are '+' separated, kernel expects ':' separated */
495 +               while ( (cp = strchr(mp->h_host, '+')) )
496 +                      *cp = ':';
497 +       }
498 +       return res;
499 +}
500 +
501 +/* @data is a string of form path@host[+host][:path@host[+host]]
502 + */
503 +static struct servers *method_list(char *data)
504 +{
505 +       char *copy, *ptr=data;
506 +       char **list;
507 +       int i, listsize;
508 +       struct servers *rv=NULL;
509 +
510 +       xlog(L_NOTICE, "method_list(%s)\n", data);
511 +       for (ptr--, listsize=1; ptr; ptr=index(ptr, ':'), listsize++)
512 +               ptr++;
513 +       list = malloc(listsize * sizeof(char *));
514 +       copy = strdup(data);
515 +       if (copy)
516 +               xlog(L_NOTICE, "converted to %s\n", copy);
517 +       if (list && copy) {
518 +               ptr = copy;
519 +               for (i=0; i<listsize; i++) {
520 +                       list[i] = strsep(&ptr, ":");
521 +               }
522 +               rv = parse_list(list);
523 +       }
524 +       free(copy);
525 +       free(list);
526 +       replicas_print(rv);
527 +       return rv;
528 +}
529 +
530 +/* Returns appropriately filled struct servers, or NULL if had a problem */
531 +struct servers *replicas_lookup(int method, char *data, char *key)
532 +{
533 +       struct servers *sp=NULL;
534 +       switch(method) {
535 +       case FSLOC_NONE:
536 +               break;
537 +       case FSLOC_REFER:
538 +               sp = method_list(data);
539 +               if (sp)
540 +                       sp->h_referral = 1;
541 +               break;
542 +       case FSLOC_REPLICA:
543 +               sp = method_list(data);
544 +               if (sp)
545 +                       sp->h_referral = 0;
546 +               break;
547 +#ifdef DEBUG
548 +       case FSLOC_STUB:
549 +               sp = method_stub(data);
550 +               break;
551 +#endif
552 +       default:
553 +               xlog(L_WARNING, "Unknown method = %i", method);
554 +       }
555 +       replicas_print(sp);
556 +       return sp;
557 +}
558 +
559 +void release_replicas(struct servers *server)
560 +{
561 +       int i;
562 +
563 +       if (!server) return;
564 +       for (i = 0; i < server->h_num; i++) {
565 +               free(server->h_mp[i]->h_host);
566 +               free(server->h_mp[i]->h_path);
567 +               free(server->h_mp[i]);
568 +       }
569 +       free(server);
570 +}
571 diff -puN /dev/null utils/mountd/fsloc.h
572 --- /dev/null   2007-02-26 18:43:11.800773059 -0500
573 +++ nfs-utils-1.0.11-kwc/utils/mountd/fsloc.h   2007-02-26 18:52:08.764976000 -0500
574 @@ -0,0 +1,50 @@
575 +/*
576 + * COPYRIGHT (c) 2006
577 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
578 + * ALL RIGHTS RESERVED
579 + *
580 + * Permission is granted to use, copy, create derivative works
581 + * and redistribute this software and such derivative works
582 + * for any purpose, so long as the name of The University of
583 + * Michigan is not used in any advertising or publicity
584 + * pertaining to the use of distribution of this software
585 + * without specific, written prior authorization.  If the
586 + * above copyright notice or any other identification of the
587 + * University of Michigan is included in any copy of any
588 + * portion of this software, then the disclaimer below must
589 + * also be included.
590 + *
591 + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
592 + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
593 + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
594 + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
595 + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
596 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
597 + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
598 + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
599 + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
600 + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
601 + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
602 + * SUCH DAMAGES.
603 + */
604 +
605 +#ifndef FSLOC_H
606 +#define FSLOC_H
607 +
608 +#define FSLOC_MAX_LIST 40
609 +
610 +struct mount_point {
611 +       char *h_host;
612 +       char *h_path;
613 +};
614 +
615 +struct servers {
616 +       int h_num;
617 +       struct mount_point *h_mp[FSLOC_MAX_LIST];
618 +       int h_referral;         /* 0=replica, 1=referral */
619 +};
620 +
621 +struct servers *replicas_lookup(int method, char *data, char *key);
622 +void release_replicas(struct servers *server);
623 +
624 +#endif /* FSLOC_H */
625 diff -puN support/include/fstab.h~CITI_NFS4_ALL support/include/fstab.h
626 --- nfs-utils-1.0.11/support/include/fstab.h~CITI_NFS4_ALL      2007-02-26 18:52:09.366915000 -0500
627 +++ nfs-utils-1.0.11-kwc/support/include/fstab.h        2007-02-26 18:52:11.399987000 -0500
628 @@ -3,6 +3,10 @@
629  
630  #include "nfs_mntent.h"
631  
632 +#ifndef _PATH_FSTAB
633 +#define _PATH_FSTAB "/etc/fstab"
634 +#endif
635 +
636  int mtab_is_writable(void);
637  int mtab_does_not_exist(void);
638  
639 @@ -16,6 +20,10 @@ struct mntentchn *getmntoptfile (const c
640  struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
641  struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
642  
643 +struct mntentchn *fstab_head (void);
644 +struct mntentchn *getfsfile (const char *file);
645 +struct mntentchn *getfsspec (const char *spec);
646 +
647  void lock_mtab (void);
648  void unlock_mtab (void);
649  void update_mtab (const char *special, nfs_mntent_t *with);
650 diff -puN support/include/nfs_mntent.h~CITI_NFS4_ALL support/include/nfs_mntent.h
651 --- nfs-utils-1.0.11/support/include/nfs_mntent.h~CITI_NFS4_ALL 2007-02-26 18:52:09.630659000 -0500
652 +++ nfs-utils-1.0.11-kwc/support/include/nfs_mntent.h   2007-02-26 18:52:11.440946000 -0500
653 @@ -7,10 +7,10 @@
654  #define _NFS_MNTENT_H
655  
656  typedef struct nfs_mntent_s {
657 -       const char *mnt_fsname;
658 -       const char *mnt_dir;
659 -       const char *mnt_type;
660 -       const char *mnt_opts;
661 +       char *mnt_fsname;
662 +       char *mnt_dir;
663 +       char *mnt_type;
664 +       char *mnt_opts;
665         int mnt_freq;
666         int mnt_passno;
667  } nfs_mntent_t;
668 diff -puN support/nfs/fstab.c~CITI_NFS4_ALL support/nfs/fstab.c
669 --- nfs-utils-1.0.11/support/nfs/fstab.c~CITI_NFS4_ALL  2007-02-26 18:52:09.908463000 -0500
670 +++ nfs-utils-1.0.11-kwc/support/nfs/fstab.c    2007-02-26 18:52:11.493894000 -0500
671 @@ -78,10 +78,10 @@ mtab_is_writable() {
672  
673  /* Contents of mtab and fstab ---------------------------------*/
674  
675 -struct mntentchn mounttable;
676 -static int got_mtab = 0;
677 +struct mntentchn mounttable, fstab;
678 +static int got_mtab = 0, got_fstab = 0;
679  
680 -static void read_mounttable(void);
681 +static void read_mounttable(void), read_fstab(void);
682  
683  struct mntentchn *
684  mtab_head() {
685 @@ -96,6 +96,13 @@ my_free(const void *s) {
686                 free((void *) s);
687  }
688  
689 +struct mntentchn *
690 +fstab_head() {
691 +       if (!got_fstab)
692 +               read_fstab();
693 +       return &fstab;
694 +}
695 +
696  static void
697  discard_mntentchn(struct mntentchn *mc0) {
698         struct mntentchn *mc, *mc1;
699 @@ -167,6 +174,26 @@ read_mounttable() {
700          read_mntentchn(mfp, fnam, mc);
701  }
702  
703 +static void
704 +read_fstab() {
705 +       mntFILE *mfp = NULL;
706 +       const char *fnam;
707 +       struct mntentchn *mc = &fstab;
708 +
709 +       got_fstab = 1;
710 +       mc->nxt = mc->prev = NULL;
711 +
712 +       fnam = _PATH_FSTAB;
713 +       mfp = nfs_setmntent (fnam, "r");
714 +       if (mfp == NULL || mfp->mntent_fp == NULL) {
715 +               int errsv = errno;
716 +               error(_("warning: can't open %s: %s"),
717 +                       _PATH_FSTAB, strerror (errsv));
718 +               return;
719 +       }
720 +       read_mntentchn(mfp, fnam, mc);
721 +}
722 +
723  /*
724   * Given the directory name NAME, and the place MCPREV we found it last time,
725   * try to find more occurrences.
726 @@ -201,6 +228,30 @@ getmntdevbackward (const char *name, str
727         return NULL;
728  }
729  
730 +/* Find the dir FILE in fstab.  */
731 +struct mntentchn *
732 +getfsfile (const char *file) {
733 +       struct mntentchn *mc, *mc0;
734 +
735 +       mc0 = fstab_head();
736 +       for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
737 +               if (streq(mc->m.mnt_dir, file))
738 +                       return mc;
739 +       return NULL;
740 +}
741 +
742 +/* Find the device SPEC in fstab.  */
743 +struct mntentchn *
744 +getfsspec (const char *spec) {
745 +       struct mntentchn *mc, *mc0;
746 +
747 +       mc0 = fstab_head();
748 +       for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
749 +               if (streq(mc->m.mnt_fsname, spec))
750 +                       return mc;
751 +       return NULL;
752 +}
753 +
754  /* Updating mtab ----------------------------------------------*/
755  
756  /* Flag for already existing lock file. */
757 diff -puN utils/mount/mount.c~CITI_NFS4_ALL utils/mount/mount.c
758 --- nfs-utils-1.0.11/utils/mount/mount.c~CITI_NFS4_ALL  2007-02-26 18:52:10.515323000 -0500
759 +++ nfs-utils-1.0.11-kwc/utils/mount/mount.c    2007-02-26 18:52:16.671458000 -0500
760 @@ -28,6 +28,7 @@
761  #include <sys/mount.h>
762  #include <getopt.h>
763  #include <mntent.h>
764 +#include <pwd.h>
765  
766  #include "fstab.h"
767  #include "xcommon.h"
768 @@ -43,6 +44,7 @@ char *progname;
769  int nomtab;
770  int verbose;
771  int mounttype;
772 +int sloppy;
773  
774  static struct option longopts[] = {
775    { "fake", 0, 0, 'f' },
776 @@ -74,6 +76,12 @@ struct opt_map {
777    int  mask;                    /* flag mask value */
778  };
779  
780 +/* Custom mount options for our own purposes.  */
781 +/* Maybe these should now be freed for kernel use again */
782 +#define MS_DUMMY       0x00000000
783 +#define MS_USERS       0x40000000
784 +#define MS_USER                0x20000000
785 +
786  static const struct opt_map opt_map[] = {
787    { "defaults", 0, 0, 0         },      /* default options */
788    { "ro",       1, 0, MS_RDONLY },      /* read-only */
789 @@ -90,6 +98,18 @@ static const struct opt_map opt_map[] = 
790    { "remount",  0, 0, MS_REMOUNT},      /* Alter flags of mounted FS */
791    { "bind",     0, 0, MS_BIND   },      /* Remount part of tree elsewhere */
792    { "rbind",    0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
793 +  { "auto",     0, 0, MS_DUMMY },       /* Can be mounted using -a */
794 +  { "noauto",   0, 0, MS_DUMMY },       /* Can  only be mounted explicitly */
795 +  { "users",    0, 0, MS_USERS  },      /* Allow ordinary user to mount */
796 +  { "nousers",  0, 1, MS_USERS  },      /* Forbid ordinary user to mount */
797 +  { "user",     0, 0, MS_USER   },      /* Allow ordinary user to mount */
798 +  { "nouser",   0, 1, MS_USER   },      /* Forbid ordinary user to mount */
799 +  { "owner",    0, 0, MS_DUMMY  },      /* Let the owner of the device mount */
800 +  { "noowner",  0, 0, MS_DUMMY  },      /* Device owner has no special privs */
801 +  { "group",    0, 0, MS_DUMMY  },      /* Let the group of the device mount */
802 +  { "nogroup",  0, 0, MS_DUMMY  },      /* Device group has no special privs */
803 +  { "_netdev",  0, 0, MS_DUMMY},        /* Device requires network */
804 +  { "comment",  0, 0, MS_DUMMY},        /* fstab comment only (kudzu,_netdev)*/
805  
806    /* add new options here */
807  #ifdef MS_NOSUB
808 @@ -104,6 +124,7 @@ static const struct opt_map opt_map[] = 
809    { "mand",     0, 0, MS_MANDLOCK },    /* Allow mandatory locks on this FS */
810    { "nomand",   0, 1, MS_MANDLOCK },    /* Forbid mandatory locks on this FS */
811  #endif
812 +  { "loop",     1, 0, MS_DUMMY   },      /* use a loop device */
813  #ifdef MS_NOATIME
814    { "atime",    0, 1, MS_NOATIME },     /* Update access time */
815    { "noatime",  0, 0, MS_NOATIME },     /* Do not update access time */
816 @@ -121,6 +142,12 @@ static char * fix_opts_string (int flags
817         char *new_opts;
818  
819         new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
820 +       if (flags & MS_USER) {
821 +               struct passwd *pw = getpwuid(getuid());
822 +               if(pw)
823 +                       new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name);
824 +       }
825 +       
826         for (om = opt_map; om->opt != NULL; om++) {
827                 if (om->skip)
828                         continue;
829 @@ -132,22 +159,54 @@ static char * fix_opts_string (int flags
830         if (extra_opts && *extra_opts) {
831                 new_opts = xstrconcat3(new_opts, ",", extra_opts);
832         }
833 +
834         return new_opts;
835  }
836  
837 +static inline void dup_mntent(struct mntent *ment, nfs_mntent_t *nment)
838 +{
839 +       /* Not sure why nfs_mntent_t should exist */
840 +       nment->mnt_fsname = strdup(ment->mnt_fsname);
841 +       nment->mnt_dir = strdup(ment->mnt_dir);
842 +       nment->mnt_type = strdup(ment->mnt_type);
843 +       nment->mnt_opts = strdup(ment->mnt_opts);
844 +       nment->mnt_freq = ment->mnt_freq;
845 +       nment->mnt_passno = ment->mnt_passno;
846 +}
847 +static inline void 
848 +free_mntent(nfs_mntent_t *ment, int remount)
849 +{
850 +       free(ment->mnt_fsname);
851 +       free(ment->mnt_dir);
852 +       free(ment->mnt_type);
853 +       /* 
854 +        * Note: free(ment->mnt_opts) happens in discard_mntentchn()
855 +        * via update_mtab() on remouts
856 +        */
857 +        if (!remount)
858 +               free(ment->mnt_opts);
859 +}
860  
861  int add_mtab(char *fsname, char *mount_point, char *fstype, int flags, char *opts, int freq, int passno)
862  {
863         struct mntent ment;
864 -       int fd;
865         FILE *mtab;
866  
867         ment.mnt_fsname = fsname;
868         ment.mnt_dir = mount_point;
869         ment.mnt_type = fstype;
870         ment.mnt_opts = fix_opts_string(flags, opts);
871 -       ment.mnt_freq = 0;
872 -       ment.mnt_passno= 0;
873 +       ment.mnt_freq = freq;
874 +       ment.mnt_passno= passno;
875 +
876 +       if(flags & MS_REMOUNT) {
877 +               nfs_mntent_t nment;
878 +               
879 +               dup_mntent(&ment, &nment);
880 +               update_mtab(nment.mnt_dir, &nment);
881 +               free_mntent(&nment, 1);
882 +               return 0;
883 +       }
884  
885         lock_mtab();
886  
887 @@ -191,6 +250,7 @@ void mount_usage()
888         printf("\t-w\t\tMount file system read-write\n");
889         printf("\t-f\t\tFake mount, don't actually mount\n");
890         printf("\t-n\t\tDo not update /etc/mtab\n");
891 +       printf("\t-s\t\tTolerate sloppy mount options rather than failing.\n");
892         printf("\t-h\t\tPrint this help\n");
893         printf("\tversion\t\tnfs4 - NFS version 4, nfs - older NFS version supported\n");
894         printf("\tnfsoptions\tRefer mount.nfs(8) or nfs(5)\n\n");
895 @@ -225,52 +285,98 @@ static void parse_opts (const char *opti
896  {
897         if (options != NULL) {
898                 char *opts = xstrdup(options);
899 -               char *opt;
900 -               int len = strlen(opts) + 20;
901 -
902 +               char *opt, *p;
903 +               int len = strlen(opts) + 256;
904 +               int open_quote = 0;
905
906                 *extra_opts = xmalloc(len);
907                 **extra_opts = '\0';
908  
909 -               for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
910 -                       parse_opt(opt, flags, *extra_opts, len);
911 -
912 +               for (p=opts, opt=NULL; p && *p; p++) {
913 +                       if (!opt)
914 +                               opt = p;                /* begin of the option item */
915 +                       if (*p == '"') 
916 +                               open_quote ^= 1;        /* reverse the status */
917 +                       if (open_quote)
918 +                               continue;               /* still in quoted block */
919 +                       if (*p == ',')
920 +                               *p = '\0';              /* terminate the option item */
921 +                       /* end of option item or last item */
922 +                       if (*p == '\0' || *(p+1) == '\0') {
923 +                               parse_opt(opt, flags, *extra_opts, len);
924 +                               opt = NULL;
925 +                       }
926 +               } 
927                 free(opts);
928         }
929 +}
930  
931 +/*
932 + * Look for an option in a comma-separated list
933 + */
934 +int
935 +contains(const char *list, const char *s) {
936 +       int n = strlen(s);
937 +
938 +       while (*list) {
939 +               if (strncmp(list, s, n) == 0 &&
940 +                 (list[n] == 0 || list[n] == ','))
941 +                       return 1;
942 +               while (*list && *list++ != ',') ;
943 +       }
944 +       return 0;
945 +}
946 +
947 +/*
948 + * If list contains "user=peter" and we ask for "user=", return "peter"
949 + */
950 +char *
951 +get_value(const char *list, const char *s) {
952 +       const char *t;
953 +       int n = strlen(s);
954 +
955 +       while (*list) {
956 +               if (strncmp(list, s, n) == 0) {
957 +                       s = t = list+n;
958 +                       while (*s && *s != ',')
959 +                               s++;
960 +                       return xstrndup(t, s-t);
961 +               }
962 +               while (*list && *list++ != ',') ;
963 +       }
964 +       return 0;
965  }
966  
967  static void mount_error(char *node)
968  {
969         switch(errno) {
970                 case ENOTDIR:
971 -                       printf("%s: mount point %s is not a directory\n", progname, node);
972 +                       fprintf(stderr, "%s: mount point %s is not a directory\n", progname, node);
973                         break;
974                 case EBUSY:
975 -                       printf("%s: %s is already mounted or busy\n", progname, node);
976 +                       fprintf(stderr, "%s: %s is already mounted or busy\n", progname, node);
977                         break;
978                 case ENOENT:
979 -                       printf("%s: mount point %s does not exist\n", progname, node);
980 +                       fprintf(stderr, "%s: mount point %s does not exist\n", progname, node);
981                         break;
982                 default:
983 -                       printf("%s: %s\n", progname, strerror(errno));
984 +                       fprintf(stderr, "%s: %s\n", progname, strerror(errno));
985         }
986  }
987 +#define NFS_MOUNT_VERS_DEFAULT 3
988  
989  int main(int argc, char *argv[])
990  {
991 -       int c, flags = 0, nfs_mount_vers = 0, mnt_err = 1, fake = 0;
992 +       int c, flags = 0, nfs_mount_vers, mnt_err = 1, fake = 0;
993         char *spec, *mount_point, *extra_opts = NULL;
994         char *mount_opts = NULL, *p;
995 +       struct mntentchn *mc;
996 +       uid_t uid = getuid();
997  
998         progname = argv[0];
999         if ((p = strrchr(progname, '/')) != NULL)
1000                 progname = p+1;
1001  
1002 -       if (getuid() != 0) {
1003 -               printf("%s: only root can do that.\n", progname);
1004 -               exit(1);
1005 -       }
1006 -
1007         if(!strncmp(progname, "umount", strlen("umount"))) {
1008                 if(argc < 2) {
1009                         umount_usage();
1010 @@ -292,7 +398,11 @@ int main(int argc, char *argv[])
1011                 return 0;
1012         }
1013  
1014 -       while ((c = getopt_long (argc - 2, argv + 2, "rt:vVwfno:h",
1015 +       nfs_mount_vers = NFS_MOUNT_VERS_DEFAULT;
1016 +       if (!strcmp(progname, "mount.nfs4"))
1017 +               nfs_mount_vers = 4;
1018 +
1019 +       while ((c = getopt_long (argc - 2, argv + 2, "rt:vVwfno:hs",
1020                                 longopts, NULL)) != -1) {
1021                 switch (c) {
1022                 case 'r':
1023 @@ -322,6 +432,9 @@ int main(int argc, char *argv[])
1024                         else
1025                                 mount_opts = xstrdup(optarg);
1026                         break;
1027 +               case 's':
1028 +                       ++sloppy;
1029 +                       break;
1030                 case 128: /* bind */
1031                         mounttype = MS_BIND;
1032                         break;
1033 @@ -352,31 +465,59 @@ int main(int argc, char *argv[])
1034  
1035         spec = argv[1];
1036         mount_point = canonicalize(argv[2]);
1037 -       
1038 +
1039         parse_opts(mount_opts, &flags, &extra_opts);
1040  
1041 -       if (!strcmp(progname, "mount.nfs4") || nfs_mount_vers == 4) {
1042 -               nfs_mount_vers = 4;
1043 -               mnt_err = nfs4mount(spec, mount_point, &flags, &extra_opts, &mount_opts, 0);
1044 +       if (uid != 0 && !(flags & MS_USERS) && !(flags & MS_USER)) {
1045 +               fprintf(stderr, "%s: permission denied\n", progname);
1046 +               exit(1);
1047 +       }
1048 +
1049 +       if ((flags & MS_USER || flags & MS_USERS) && uid != 0) {
1050 +               /* check if fstab has entry, and further see if the user or users option is given */
1051 +               if ((mc = getfsspec(spec)) == NULL &&
1052 +                   (mc = getfsfile(spec)) == NULL) {
1053 +                       fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1054 +                       exit(1);
1055 +               }
1056 +               else {
1057 +                       if((flags & MS_USER) && !contains(mc->m.mnt_opts, "user")) {
1058 +                               fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1059 +                               exit(1);
1060 +                       }
1061 +                       if((flags & MS_USERS) && !contains(mc->m.mnt_opts, "users")) {
1062 +                               fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1063 +                               exit(1);
1064 +                       }
1065 +               }
1066 +       }
1067 +
1068 +       if (nfs_mount_vers == 4) {
1069 +               mnt_err = nfs4mount(spec, mount_point, &flags, 
1070 +                       &extra_opts, &mount_opts, 0);
1071         }
1072         else {
1073                 if (!strcmp(progname, "mount.nfs")) {
1074                         mnt_err = nfsmount(spec, mount_point, &flags,
1075 -                                       &extra_opts, &mount_opts, &nfs_mount_vers, 0);
1076 +                                       &extra_opts, &mount_opts,  0);
1077                 }
1078         }
1079 +       if (fake)
1080 +               return 0;
1081 +       if (mnt_err)
1082 +               exit(EX_FAIL);
1083  
1084 -       if (!mnt_err && !fake) {
1085 -               mnt_err = do_mount_syscall(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
1086 -               
1087 -               if(mnt_err) {
1088 -                       mount_error(mount_point);
1089 -                       exit(-1);
1090 -               }
1091 +       mnt_err = do_mount_syscall(spec, mount_point,
1092 +                       nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
1093 +
1094 +       if(mnt_err) {
1095 +               mount_error(mount_point);
1096 +               exit(EX_FAIL);
1097 +       }
1098  
1099 -               if(!nomtab)
1100 -                       add_mtab(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs",
1101 -                                flags, extra_opts, 0, 0);
1102 +       if(!nomtab) {
1103 +               add_mtab(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs",
1104 +                        flags, extra_opts, 0, 0);
1105         }
1106  
1107         return 0;
1108 diff -puN utils/mount/nfs_mount.h~CITI_NFS4_ALL utils/mount/nfs_mount.h
1109 --- nfs-utils-1.0.11/utils/mount/nfs_mount.h~CITI_NFS4_ALL      2007-02-26 18:52:10.854011000 -0500
1110 +++ nfs-utils-1.0.11-kwc/utils/mount/nfs_mount.h        2007-02-26 18:52:14.652380000 -0500
1111 @@ -78,7 +78,9 @@ struct nfs_mount_data {
1112  #define AUTH_GSS_SPKMP         390011
1113  #endif
1114  
1115 -int nfsmount(const char *, const char *, int *, char **, char **, int *, int);
1116 +int nfsmount(const char *, const char *, int *, char **, char **, int);
1117  void mount_errors(char *, int, int);
1118 +int contains(const char *, const char *);
1119 +char *get_value(const char *, const char *);
1120  
1121  #endif /* _NFS_MOUNT_H */
1122 diff -puN utils/mount/nfsumount.c~CITI_NFS4_ALL utils/mount/nfsumount.c
1123 --- nfs-utils-1.0.11/utils/mount/nfsumount.c~CITI_NFS4_ALL      2007-02-26 18:52:11.207011000 -0500
1124 +++ nfs-utils-1.0.11-kwc/utils/mount/nfsumount.c        2007-02-26 18:52:16.013751000 -0500
1125 @@ -19,16 +19,19 @@
1126  
1127  #include <stdio.h>
1128  #include <errno.h>
1129 +#include <unistd.h>
1130  #include <getopt.h>
1131  #include <mntent.h>
1132  #include <sys/mount.h>
1133  #include <ctype.h>
1134 +#include <pwd.h>
1135  
1136  #include "xcommon.h"
1137  #include "fstab.h"
1138  #include "nls.h"
1139  #include "conn.h"
1140  
1141 +#include "nfs_mount.h"
1142  #include "mount_constants.h"
1143  #include "mount.h"
1144  #include "nfsumount.h"
1145 @@ -98,9 +101,9 @@ int nfs_call_umount(clnt_addr_t *mnt_ser
1146         }
1147         mnt_closeclnt(clnt, msock);
1148         if (res == RPC_SUCCESS)
1149 -               return 1;
1150 +               return 0;
1151   out_bad:
1152 -       return 0;
1153 +       return 1;
1154  }
1155  
1156  u_int get_mntproto(const char *);
1157 @@ -249,9 +252,6 @@ int add_mtab2(const char *spec, const ch
1158          return 1;
1159  }
1160  
1161 -/*
1162 - * Returns 1 if everything went well, else 0.
1163 - */
1164  int _nfsumount(const char *spec, const char *opts)
1165  {
1166         char *hostname;
1167 @@ -307,8 +307,8 @@ int _nfsumount(const char *spec, const c
1168                 goto out_bad;
1169         return nfs_call_umount(&mnt_server, &dirname);
1170   out_bad:
1171 -       printf("%s: %s: not found or not mounted\n", progname, spec);
1172 -       return 0;
1173 +       fprintf(stderr, "%s: %s: not found / mounted or server not reachable\n", progname, spec);
1174 +       return 1;
1175  }
1176  
1177  static struct option umount_longopts[] =
1178 @@ -334,7 +334,7 @@ void umount_usage()
1179  
1180  int nfsumount(int argc, char *argv[])
1181  {
1182 -       int c, ret;
1183 +       int c, ret, v4=0;
1184         char *spec;
1185         struct mntentchn *mc;
1186  
1187 @@ -372,20 +372,33 @@ int nfsumount(int argc, char *argv[])
1188         mc = getmntdirbackward(spec, NULL);
1189         if (!mc)
1190                 mc = getmntdevbackward(spec, NULL);
1191 -       if (!mc && verbose)
1192 -               printf(_("Could not find %s in mtab\n"), spec);
1193 -
1194 -       if(mc) {
1195 -               ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
1196 -               if(ret)
1197 -                       ret = add_mtab2(mc->m.mnt_fsname, mc->m.mnt_dir,
1198 -                               mc->m.mnt_type, mc->m.mnt_opts, mc);
1199 +       if (mc == NULL) {
1200 +               fprintf(stderr, "%s: Unable to find '%s' in mount table\n",
1201 +                               progname, spec);
1202 +               exit(1);
1203         }
1204 -       else {
1205 -               ret = _nfsumount(spec, NULL);
1206 -               if(ret)
1207 -                       ret = add_mtab2(spec, spec, spec, spec, NULL);
1208 +       if(contains(mc->m.mnt_opts, "user") && getuid() != 0) {
1209 +               struct passwd *pw = getpwuid(getuid());
1210 +               if(!pw || strcmp(pw->pw_name, get_value(mc->m.mnt_opts, "user="))) {
1211 +                       fprintf(stderr, "%s: permission denied to unmount %s\n",
1212 +                                       progname, spec);
1213 +                       exit(1);
1214 +               }
1215 +       } else {
1216 +               if(!contains(mc->m.mnt_opts, "users") && getuid() != 0) {
1217 +                       fprintf(stderr, "%s: only root can unmount %s from %s\n",
1218 +                                       progname, mc->m.mnt_fsname, mc->m.mnt_dir);
1219 +                       exit(1);
1220 +               }
1221         }
1222 +       v4 = contains(mc->m.mnt_type, "nfs4");
1223 +
1224 +       ret = 0;
1225 +       if(!force && !lazy && !v4)
1226 +               ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
1227 +       if(!ret)
1228 +               ret = add_mtab2(mc->m.mnt_fsname, mc->m.mnt_dir,
1229 +                       mc->m.mnt_type, mc->m.mnt_opts, mc);
1230  
1231         return(ret);
1232  }
1233 diff -puN utils/mount/nfs4mount.c~CITI_NFS4_ALL utils/mount/nfs4mount.c
1234 --- nfs-utils-1.0.11/utils/mount/nfs4mount.c~CITI_NFS4_ALL      2007-02-26 18:52:12.678257000 -0500
1235 +++ nfs-utils-1.0.11-kwc/utils/mount/nfs4mount.c        2007-02-26 18:52:13.199107000 -0500
1236 @@ -50,6 +50,7 @@
1237  #endif
1238  
1239  extern int verbose;
1240 +extern int sloppy;
1241  
1242  char *IDMAPLCK = DEFAULT_DIR "/rpcidmapd";
1243  #define idmapd_check() do { \
1244 @@ -335,7 +336,7 @@ int nfs4mount(const char *spec, const ch
1245                                 nocto = !val;
1246                         else if (!strcmp(opt, "ac"))
1247                                 noac = !val;
1248 -                       else {
1249 +                       else if (!sloppy) {
1250                                 printf(_("unknown nfs mount option: "
1251                                          "%s%s\n"), val ? "" : "no", opt);
1252                                 goto fail;
1253 diff -puN utils/mount/nfsmount.c~CITI_NFS4_ALL utils/mount/nfsmount.c
1254 --- nfs-utils-1.0.11/utils/mount/nfsmount.c~CITI_NFS4_ALL       2007-02-26 18:52:13.028107000 -0500
1255 +++ nfs-utils-1.0.11-kwc/utils/mount/nfsmount.c 2007-02-26 18:52:16.886299000 -0500
1256 @@ -104,6 +104,7 @@ typedef union {
1257  static char errbuf[BUFSIZ];
1258  static char *erreob = &errbuf[BUFSIZ];
1259  extern int verbose;
1260 +extern int sloppy;
1261  
1262  /* Convert RPC errors into strings */
1263  int rpc_strerror(int);
1264 @@ -547,15 +548,31 @@ parse_options(char *old_opts, struct nfs
1265         struct pmap *mnt_pmap = &mnt_server->pmap;
1266         struct pmap *nfs_pmap = &nfs_server->pmap;
1267         int len;
1268 -       char *opt, *opteq;
1269 +       char *opt, *opteq, *p, *opt_b;
1270         char *mounthost = NULL;
1271         char cbuf[128];
1272 +       int open_quote = 0;
1273  
1274         data->flags = 0;
1275         *bg = 0;
1276  
1277         len = strlen(new_opts);
1278 -       for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
1279 +       for (p=old_opts, opt_b=NULL; p && *p; p++) {
1280 +               if (!opt_b)
1281 +                       opt_b = p;              /* begin of the option item */
1282 +               if (*p == '"') 
1283 +                       open_quote ^= 1;        /* reverse the status */
1284 +               if (open_quote)
1285 +                       continue;               /* still in quoted block */
1286 +               if (*p == ',')
1287 +                       *p = '\0';              /* terminate the option item */
1288 +               if (*p == '\0' || *(p+1) == '\0') {
1289 +                       opt = opt_b;            /* opt is useful now */
1290 +                       opt_b = NULL;
1291 +               }
1292 +               else
1293 +                       continue;               /* still somewhere in the option item */
1294 +
1295                 if (strlen(opt) >= sizeof(cbuf))
1296                         goto bad_parameter;
1297                 if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
1298 @@ -606,13 +623,13 @@ parse_options(char *old_opts, struct nfs
1299                         } else if (!strcmp(opt, "namlen")) {
1300                                 if (nfs_mount_version >= 2)
1301                                         data->namlen = val;
1302 -                               else
1303 +                               else if (!sloppy)
1304                                         goto bad_parameter;
1305  #endif
1306                         } else if (!strcmp(opt, "addr")) {
1307                                 /* ignore */;
1308                                 continue;
1309 -                       } else
1310 +                       } else if (!sloppy)
1311                                 goto bad_parameter;
1312                         sprintf(cbuf, "%s=%s,", opt, opteq+1);
1313                 } else if (opteq) {
1314 @@ -629,7 +646,7 @@ parse_options(char *old_opts, struct nfs
1315                                         mnt_pmap->pm_prot = IPPROTO_TCP;
1316                                         data->flags |= NFS_MOUNT_TCP;
1317  #endif
1318 -                               } else
1319 +                               } else if (!sloppy)
1320                                         goto bad_parameter;
1321  #if NFS_MOUNT_VERSION >= 5
1322                         } else if (!strcmp(opt, "sec")) {
1323 @@ -658,7 +675,7 @@ parse_options(char *old_opts, struct nfs
1324                                         data->pseudoflavor = AUTH_GSS_SPKMI;
1325                                 else if (!strcmp(secflavor, "spkm3p"))
1326                                         data->pseudoflavor = AUTH_GSS_SPKMP;
1327 -                               else {
1328 +                               else if (!sloppy) {
1329                                         printf(_("Warning: Unrecognized security flavor %s.\n"),
1330                                                 secflavor);
1331                                         goto bad_parameter;
1332 @@ -670,14 +687,24 @@ parse_options(char *old_opts, struct nfs
1333                                                    strcspn(opteq+1," \t\n\r,"));
1334                          else if (!strcmp(opt, "context")) {
1335                                 char *context = opteq + 1;
1336 +                               int ctxlen = strlen(context);
1337                                 
1338 -                               if (strlen(context) > NFS_MAX_CONTEXT_LEN) {
1339 +                               if (ctxlen > NFS_MAX_CONTEXT_LEN) {
1340                                         printf(_("context parameter exceeds limit of %d\n"),
1341                                                  NFS_MAX_CONTEXT_LEN);
1342                                         goto bad_parameter;
1343                                 }
1344 -                               strncpy(data->context, context, NFS_MAX_CONTEXT_LEN);
1345 -                       } else
1346 +                               /* The context string is in the format of
1347 +                                * "system_u:object_r:...".  We only want
1348 +                                * the context str between the quotes.
1349 +                                */
1350 +                               if (*context == '"')
1351 +                                       strncpy(data->context, context+1, 
1352 +                                                       ctxlen-2);
1353 +                               else
1354 +                                       strncpy(data->context, context, 
1355 +                                                       NFS_MAX_CONTEXT_LEN);
1356 +                       } else if (!sloppy)
1357                                 goto bad_parameter;
1358                         sprintf(cbuf, "%s=%s,", opt, opteq+1);
1359                 } else {
1360 @@ -764,9 +791,11 @@ parse_options(char *old_opts, struct nfs
1361  #endif
1362                         } else {
1363                         bad_option:
1364 -                               printf(_("Unsupported nfs mount option: "
1365 -                                        "%s%s\n"), val ? "" : "no", opt);
1366 -                               goto out_bad;
1367 +                               if (!sloppy) {
1368 +                                       printf(_("Unsupported nfs mount option: "
1369 +                                                "%s%s\n"), val ? "" : "no", opt);
1370 +                                       goto out_bad;
1371 +                               }
1372                         }
1373                         sprintf(cbuf, val ? "%s,":"no%s,", opt);
1374                 }
1375 @@ -815,8 +844,7 @@ nfsmnt_check_compat(const struct pmap *n
1376  
1377  int
1378  nfsmount(const char *spec, const char *node, int *flags,
1379 -        char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1380 -        int running_bg)
1381 +        char **extra_opts, char **mount_opts, int running_bg)
1382  {
1383         static char *prev_bg_host;
1384         char hostdir[1024];
1385 @@ -847,9 +875,7 @@ nfsmount(const char *spec, const char *n
1386  
1387         /* The version to try is either specified or 0
1388            In case it is 0 we tell the caller what we tried */
1389 -       if (!*nfs_mount_vers)
1390 -               *nfs_mount_vers = find_kernel_nfs_mount_version();
1391 -       nfs_mount_version = *nfs_mount_vers;
1392 +       nfs_mount_version = find_kernel_nfs_mount_version();
1393  
1394         retval = EX_FAIL;
1395         fsock = -1;
1396 @@ -1090,12 +1116,14 @@ nfsmount(const char *spec, const char *n
1397  
1398                 flavor = mountres->auth_flavors.auth_flavors_val;
1399                 while (--i >= 0) {
1400 -                       if (flavor[i] == data.pseudoflavor)
1401 -                               yum = 1;
1402  #ifdef NFS_MOUNT_DEBUG
1403 -                       printf("auth flavor %d: %d\n",
1404 -                               i, flavor[i]);
1405 +                       printf("auth flavor[%d] %d\n", i, flavor[i]);
1406  #endif
1407 +                       if (flavor[i] == data.pseudoflavor ||
1408 +                               flavor[i] == AUTH_NONE) {
1409 +                               yum = 1;
1410 +                               break;
1411 +                       }
1412                 }
1413                 if (!yum) {
1414                         fprintf(stderr,
1415 diff -puN support/nfs/conn.c~CITI_NFS4_ALL support/nfs/conn.c
1416 --- nfs-utils-1.0.11/support/nfs/conn.c~CITI_NFS4_ALL   2007-02-26 18:52:15.411170000 -0500
1417 +++ nfs-utils-1.0.11-kwc/support/nfs/conn.c     2007-02-26 18:52:15.506075000 -0500
1418 @@ -98,7 +98,7 @@ int get_socket(struct sockaddr_in *saddr
1419                         return RPC_ANYSOCK;
1420                 }
1421         }
1422 -       if (type == SOCK_STREAM || type == SOCK_DGRAM) {
1423 +       if (type == SOCK_STREAM) {
1424                 cc = connect(so, (struct sockaddr *)saddr, namelen);
1425                 if (cc < 0) {
1426                         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1427 diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c
1428 --- nfs-utils-1.0.11/utils/gssd/gssd.c~CITI_NFS4_ALL    2007-02-26 18:52:17.909847000 -0500
1429 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd.c      2007-02-26 18:52:21.146491000 -0500
1430 @@ -53,7 +53,8 @@
1431  #include "gss_util.h"
1432  #include "krb5_util.h"
1433  
1434 -char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
1435 +char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
1436 +char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
1437  char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
1438  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
1439  int  use_memcache = 0;
1440 @@ -111,8 +112,8 @@ main(int argc, char *argv[])
1441                                 rpc_verbosity++;
1442                                 break;
1443                         case 'p':
1444 -                               strncpy(pipefsdir, optarg, sizeof(pipefsdir));
1445 -                               if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
1446 +                               strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
1447 +                               if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
1448                                         errx(1, "pipefs path name too long");
1449                                 break;
1450                         case 'k':
1451 @@ -130,10 +131,10 @@ main(int argc, char *argv[])
1452                                 break;
1453                 }
1454         }
1455 -       strncat(pipefsdir + strlen(pipefsdir), "/" GSSD_SERVICE_NAME,
1456 -               sizeof(pipefsdir)-strlen(pipefsdir));
1457 -       if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
1458 -               errx(1, "pipefs path name too long");
1459 +       snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
1460 +                pipefs_dir, GSSD_SERVICE_NAME);
1461 +       if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
1462 +               errx(1, "pipefs_nfsdir path name too long");
1463  
1464         if ((progname = strrchr(argv[0], '/')))
1465                 progname++;
1466 @@ -161,6 +162,8 @@ main(int argc, char *argv[])
1467  
1468         /* Process keytab file and get machine credentials */
1469         gssd_refresh_krb5_machine_creds();
1470 +       /* Determine Kerberos information from the kernel */
1471 +       gssd_obtain_kernel_krb5_info();
1472  
1473         gssd_run();
1474         printerr(0, "gssd_run returned!\n");
1475 diff -puN utils/gssd/gssd.h~CITI_NFS4_ALL utils/gssd/gssd.h
1476 --- nfs-utils-1.0.11/utils/gssd/gssd.h~CITI_NFS4_ALL    2007-02-26 18:52:18.243847000 -0500
1477 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd.h      2007-02-26 18:52:19.072395000 -0500
1478 @@ -58,7 +58,8 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
1479  
1480  
1481  
1482 -extern char                    pipefsdir[PATH_MAX];
1483 +extern char                    pipefs_dir[PATH_MAX];
1484 +extern char                    pipefs_nfsdir[PATH_MAX];
1485  extern char                    keytabfile[PATH_MAX];
1486  extern char                    ccachedir[PATH_MAX];
1487  extern int                     use_memcache;
1488 diff -puN utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL utils/gssd/gssd_main_loop.c
1489 --- nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL  2007-02-26 18:52:18.584642000 -0500
1490 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd_main_loop.c    2007-02-26 18:52:19.111395000 -0500
1491 @@ -106,9 +106,9 @@ gssd_run()
1492         dn_act.sa_flags = SA_SIGINFO;
1493         sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
1494  
1495 -       if ((fd = open(pipefsdir, O_RDONLY)) == -1) {
1496 +       if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
1497                 printerr(0, "ERROR: failed to open %s: %s\n",
1498 -                        pipefsdir, strerror(errno));
1499 +                        pipefs_nfsdir, strerror(errno));
1500                 exit(1);
1501         }
1502         fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
1503 diff -puN utils/gssd/gssd_proc.c~CITI_NFS4_ALL utils/gssd/gssd_proc.c
1504 --- nfs-utils-1.0.11/utils/gssd/gssd_proc.c~CITI_NFS4_ALL       2007-02-26 18:52:18.936395000 -0500
1505 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd_proc.c 2007-02-26 18:52:19.165395000 -0500
1506 @@ -80,19 +80,19 @@
1507   *     with an index into pollarray[], and other basic data about that client.
1508   *
1509   * Directory structure: created by the kernel nfs client
1510 - *      /pipefsdir/clntXX             : one per rpc_clnt struct in the kernel
1511 - *      /pipefsdir/clntXX/krb5        : read uid for which kernel wants
1512 - *                                      a context, write the resulting context
1513 - *      /pipefsdir/clntXX/info        : stores info such as server name
1514 + *      {pipefs_nfsdir}/clntXX             : one per rpc_clnt struct in the kernel
1515 + *      {pipefs_nfsdir}/clntXX/krb5        : read uid for which kernel wants
1516 + *                                         a context, write the resulting context
1517 + *      {pipefs_nfsdir}/clntXX/info        : stores info such as server name
1518   *
1519   * Algorithm:
1520 - *      Poll all /pipefsdir/clntXX/krb5 files.  When ready, data read
1521 + *      Poll all {pipefs_nfsdir}/clntXX/krb5 files.  When ready, data read
1522   *      is a uid; performs rpcsec_gss context initialization protocol to
1523   *      get a cred for that user.  Writes result to corresponding krb5 file
1524   *      in a form the kernel code will understand.
1525   *      In addition, we make sure we are notified whenever anything is
1526 - *      created or destroyed in pipefsdir/ or in an of the clntXX directories,
1527 - *      and rescan the whole pipefsdir when this happens.
1528 + *      created or destroyed in {pipefs_nfsdir} or in an of the clntXX directories,
1529 + *      and rescan the whole {pipefs_nfsdir} when this happens.
1530   */
1531  
1532  struct pollfd * pollarray;
1533 @@ -389,16 +389,16 @@ update_client_list(void)
1534         struct dirent **namelist;
1535         int i, j;
1536  
1537 -       if (chdir(pipefsdir) < 0) {
1538 +       if (chdir(pipefs_nfsdir) < 0) {
1539                 printerr(0, "ERROR: can't chdir to %s: %s\n",
1540 -                        pipefsdir, strerror(errno));
1541 +                        pipefs_nfsdir, strerror(errno));
1542                 return -1;
1543         }
1544  
1545 -       j = scandir(pipefsdir, &namelist, NULL, alphasort);
1546 +       j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
1547         if (j < 0) {
1548                 printerr(0, "ERROR: can't scandir %s: %s\n",
1549 -                        pipefsdir, strerror(errno));
1550 +                        pipefs_nfsdir, strerror(errno));
1551                 return -1;
1552         }
1553         update_old_clients(namelist, j);
1554 diff -puN support/include/nfslib.h~CITI_NFS4_ALL support/include/nfslib.h
1555 --- nfs-utils-1.0.11/support/include/nfslib.h~CITI_NFS4_ALL     2007-02-26 18:52:19.914943000 -0500
1556 +++ nfs-utils-1.0.11-kwc/support/include/nfslib.h       2007-02-26 18:52:20.001943000 -0500
1557 @@ -57,6 +57,9 @@ enum cle_maptypes {
1558         CLE_MAP_UGIDD,
1559  };
1560  
1561 +#define SECFLAVOR_COUNT 7
1562 +extern char *secflavor_name[SECFLAVOR_COUNT];
1563 +
1564  /*
1565   * Data related to a single exports entry as returned by getexportent.
1566   * FIXME: export options should probably be parsed at a later time to
1567 @@ -83,6 +86,8 @@ struct exportent {
1568         int             e_fslocmethod;
1569         char *          e_fslocdata;
1570         char *          e_uuid;
1571 +       int             e_secinfo_order[SECFLAVOR_COUNT+1];
1572 +       int             e_secinfo_flags[SECFLAVOR_COUNT];
1573  };
1574  
1575  struct rmtabent {
1576 @@ -96,6 +101,7 @@ struct rmtabent {
1577   */
1578  void                   setexportent(char *fname, char *type);
1579  struct exportent *     getexportent(int,int);
1580 +void                   secinfo_show(FILE *fp, struct exportent *ep);
1581  void                   putexportent(struct exportent *xep);
1582  void                   endexportent(void);
1583  struct exportent *     mkexportent(char *hname, char *path, char *opts);
1584 diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c
1585 --- nfs-utils-1.0.11/utils/gssd/krb5_util.c~CITI_NFS4_ALL       2007-02-26 18:52:20.789535000 -0500
1586 +++ nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.c 2007-02-26 18:52:21.202491000 -0500
1587 @@ -97,6 +97,7 @@
1588  #include "config.h"
1589  #include <sys/param.h>
1590  #include <rpc/rpc.h>
1591 +#include <sys/types.h>
1592  #include <sys/stat.h>
1593  #include <sys/socket.h>
1594  #include <arpa/inet.h>
1595 @@ -105,6 +106,7 @@
1596  #include <stdlib.h>
1597  #include <string.h>
1598  #include <dirent.h>
1599 +#include <fcntl.h>
1600  #include <errno.h>
1601  #include <time.h>
1602  #include <gssapi/gssapi.h>
1603 @@ -123,6 +125,10 @@
1604  /* Global list of principals/cache file names for machine credentials */
1605  struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
1606  
1607 +/* Encryption types supported by the kernel rpcsec_gss code */
1608 +int num_krb5_enctypes = 0;
1609 +krb5_enctype *krb5_enctypes = NULL;
1610 +
1611  /*==========================*/
1612  /*===  Internal routines ===*/
1613  /*==========================*/
1614 @@ -256,56 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
1615  }
1616  
1617  
1618 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1619 -/*
1620 - * this routine obtains a credentials handle via gss_acquire_cred()
1621 - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
1622 - * types negotiated.
1623 - *
1624 - * XXX Should call some function to determine the enctypes supported
1625 - * by the kernel. (Only need to do that once!)
1626 - *
1627 - * Returns:
1628 - *     0 => all went well
1629 - *     -1 => there was an error
1630 - */
1631 -
1632 -int
1633 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
1634 -{
1635 -       u_int maj_stat, min_stat;
1636 -       gss_cred_id_t credh;
1637 -       gss_OID_set_desc  desired_mechs;
1638 -       krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
1639 -       int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
1640 -
1641 -       /* We only care about getting a krb5 cred */
1642 -       desired_mechs.count = 1;
1643 -       desired_mechs.elements = &krb5oid;
1644 -
1645 -       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
1646 -                                   &desired_mechs, GSS_C_INITIATE,
1647 -                                   &credh, NULL, NULL);
1648 -
1649 -       if (maj_stat != GSS_S_COMPLETE) {
1650 -               pgsserr("gss_acquire_cred",
1651 -                       maj_stat, min_stat, &krb5oid);
1652 -               return -1;
1653 -       }
1654 -
1655 -       maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
1656 -                                            num_enctypes, &enctypes);
1657 -       if (maj_stat != GSS_S_COMPLETE) {
1658 -               pgsserr("gss_set_allowable_enctypes",
1659 -                       maj_stat, min_stat, &krb5oid);
1660 -               return -1;
1661 -       }
1662 -       sec->cred = credh;
1663 -
1664 -       return 0;
1665 -}
1666 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
1667 -
1668  /*
1669   * Obtain credentials via a key in the keytab given
1670   * a keytab handle and a gssd_k5_kt_princ structure.
1671 @@ -609,6 +565,56 @@ gssd_set_krb5_ccache_name(char *ccname)
1672  #endif
1673  }
1674  
1675 +/*
1676 + * Parse the supported encryption type information
1677 + */
1678 +static int
1679 +parse_enctypes(char *enctypes)
1680 +{
1681 +       int n = 0;
1682 +       char *curr, *comma;
1683 +       int i;
1684 +
1685 +       /* Just in case this ever gets called more than once */
1686 +       if (krb5_enctypes != NULL) {
1687 +               free(krb5_enctypes);
1688 +               krb5_enctypes = NULL;
1689 +               num_krb5_enctypes = 0;
1690 +       }
1691 +
1692 +       /* count the number of commas */
1693 +       for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
1694 +               comma = strchr(curr, ',');
1695 +               if (comma != NULL)
1696 +                       n++;
1697 +               else
1698 +                       break;
1699 +       }
1700 +       /* If no more commas and we're not at the end, there's one more value */
1701 +       if (*curr != '\0')
1702 +               n++;
1703 +
1704 +       /* Empty string, return an error */
1705 +       if (n == 0)
1706 +               return ENOENT;
1707 +
1708 +       /* Allocate space for enctypes array */
1709 +       if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
1710 +               return ENOMEM;
1711 +       }
1712 +
1713 +       /* Now parse each value into the array */
1714 +       for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
1715 +               krb5_enctypes[i++] = atoi(curr);
1716 +               comma = strchr(curr, ',');
1717 +               if (comma == NULL)
1718 +                       break;
1719 +       }
1720 +
1721 +       num_krb5_enctypes = n;
1722 +       return 0;
1723 +}
1724 +
1725  /*==========================*/
1726  /*===  External routines ===*/
1727  /*==========================*/
1728 @@ -860,3 +866,125 @@ gssd_destroy_krb5_machine_creds(void)
1729         krb5_free_context(context);
1730  }
1731  
1732 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1733 +/*
1734 + * this routine obtains a credentials handle via gss_acquire_cred()
1735 + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
1736 + * types negotiated.
1737 + *
1738 + * Returns:
1739 + *     0 => all went well
1740 + *     -1 => there was an error
1741 + */
1742 +
1743 +int
1744 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
1745 +{
1746 +       u_int maj_stat, min_stat;
1747 +       gss_cred_id_t credh;
1748 +       gss_OID_set_desc  desired_mechs;
1749 +       krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
1750 +       int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
1751 +
1752 +       /* We only care about getting a krb5 cred */
1753 +       desired_mechs.count = 1;
1754 +       desired_mechs.elements = &krb5oid;
1755 +
1756 +       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
1757 +                                   &desired_mechs, GSS_C_INITIATE,
1758 +                                   &credh, NULL, NULL);
1759 +
1760 +       if (maj_stat != GSS_S_COMPLETE) {
1761 +               pgsserr("gss_acquire_cred",
1762 +                       maj_stat, min_stat, &krb5oid);
1763 +               return -1;
1764 +       }
1765 +
1766 +       /*
1767 +        * If we failed for any reason to produce global
1768 +        * list of supported enctypes, use local default here.
1769 +        */
1770 +       if (krb5_enctypes == NULL)
1771 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
1772 +                                       &krb5oid, num_enctypes, &enctypes);
1773 +       else
1774 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
1775 +                                       &krb5oid, num_krb5_enctypes,
1776 +                                       krb5_enctypes);
1777 +       if (maj_stat != GSS_S_COMPLETE) {
1778 +               pgsserr("gss_set_allowable_enctypes",
1779 +                       maj_stat, min_stat, &krb5oid);
1780 +               return -1;
1781 +       }
1782 +       sec->cred = credh;
1783 +
1784 +       return 0;
1785 +}
1786 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
1787 +
1788 +/*
1789 + * Obtain supported enctypes from kernel.
1790 + * Set defaults if info is not available.
1791 + */
1792 +void
1793 +gssd_obtain_kernel_krb5_info(void)
1794 +{
1795 +       char enctype_file_name[128];
1796 +       char buf[1024];
1797 +       char enctypes[128];
1798 +       int nscanned;
1799 +       int fd;
1800 +       int use_default_enctypes = 0;
1801 +       int nbytes, numfields;
1802 +       char default_enctypes[] = "1,3,2";
1803 +       int code;
1804 +
1805 +       snprintf(enctype_file_name, sizeof(enctype_file_name),
1806 +                "%s/%s", pipefs_dir, "krb5_info");
1807 +
1808 +       if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
1809 +               printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
1810 +                        "Unable to open '%s'. Unable to determine "
1811 +                        "Kerberos encryption types supported by the "
1812 +                        "kernel; using defaults (%s).\n",
1813 +                        enctype_file_name, default_enctypes);
1814 +               use_default_enctypes = 1;
1815 +               goto do_the_parse;
1816 +       }
1817 +       memset(buf, 0, sizeof(buf));
1818 +       if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) {
1819 +               printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
1820 +                        "Error reading Kerberos encryption type "
1821 +                        "information file '%s'; using defaults (%s).\n",
1822 +                        enctype_file_name, default_enctypes);
1823 +               use_default_enctypes = 1;
1824 +               close(fd);
1825 +               goto do_the_parse;
1826 +       }
1827 +       close(fd);
1828 +       numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned);
1829 +       if (numfields < 1) {
1830 +               printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
1831 +                        "error parsing Kerberos encryption type "
1832 +                        "information from file '%s'; using defaults (%s).\n",
1833 +                        enctype_file_name, default_enctypes);
1834 +               use_default_enctypes = 1;
1835 +               goto do_the_parse;
1836 +       }
1837 +       if (nbytes > nscanned) {
1838 +               printerr(2, "gssd_obtain_kernel_krb5_info: "
1839 +                        "Ignoring extra information, '%s', from '%s'\n",
1840 +                        buf+nscanned, enctype_file_name);
1841 +               goto do_the_parse;
1842 +       }
1843 +  do_the_parse:
1844 +       if (use_default_enctypes)
1845 +               strcpy(enctypes, default_enctypes);
1846 +
1847 +       if ((code = parse_enctypes(enctypes)) != 0) {
1848 +               printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
1849 +                        "parse_enctypes%s failed with code %d\n",
1850 +                        use_default_enctypes ? " (with default enctypes)" : "",
1851 +                        code);
1852 +       }
1853 +}
1854 diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h
1855 --- nfs-utils-1.0.11/utils/gssd/krb5_util.h~CITI_NFS4_ALL       2007-02-26 18:52:21.065491000 -0500
1856 +++ nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.h 2007-02-26 18:52:21.305491000 -0500
1857 @@ -22,6 +22,8 @@ int  gssd_refresh_krb5_machine_creds(voi
1858  void gssd_free_krb5_machine_cred_list(char **list);
1859  void gssd_setup_krb5_machine_gss_ccache(char *servername);
1860  void gssd_destroy_krb5_machine_creds(void);
1861 +void gssd_obtain_kernel_krb5_info(void);
1862 +
1863  
1864  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1865  int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
1866 diff -puN utils/gssd/context.h~CITI_NFS4_ALL utils/gssd/context.h
1867 --- nfs-utils-1.0.11/utils/gssd/context.h~CITI_NFS4_ALL 2007-02-26 18:52:21.831041000 -0500
1868 +++ nfs-utils-1.0.11-kwc/utils/gssd/context.h   2007-02-26 18:52:22.471949000 -0500
1869 @@ -1,5 +1,5 @@
1870  /*
1871 -  Copyright (c) 2004 The Regents of the University of Michigan.
1872 +  Copyright (c) 2004-2006 The Regents of the University of Michigan.
1873    All rights reserved.
1874  
1875    Redistribution and use in source and binary forms, with or without
1876 @@ -36,6 +36,10 @@
1877  /* Hopefully big enough to hold any serialized context */
1878  #define MAX_CTX_LEN 4096
1879  
1880 +/* New context format flag values */
1881 +#define KRB5_CTX_FLAG_INITIATOR         0x00000001
1882 +#define KRB5_CTX_FLAG_CFX               0x00000002
1883 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
1884  
1885  int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
1886                                  gss_OID mech);
1887 diff -puN utils/gssd/context_lucid.c~CITI_NFS4_ALL utils/gssd/context_lucid.c
1888 --- nfs-utils-1.0.11/utils/gssd/context_lucid.c~CITI_NFS4_ALL   2007-02-26 18:52:22.123039000 -0500
1889 +++ nfs-utils-1.0.11-kwc/utils/gssd/context_lucid.c     2007-02-26 18:52:22.513907000 -0500
1890 @@ -40,6 +40,7 @@
1891  #include <stdio.h>
1892  #include <syslog.h>
1893  #include <string.h>
1894 +#include <errno.h>
1895  #include "gss_util.h"
1896  #include "gss_oids.h"
1897  #include "err_util.h"
1898 @@ -113,15 +114,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc
1899          * Note that the rfc1964 version only supports DES enctypes.
1900          */
1901         if (lctx->rfc1964_kd.ctx_key.type != 4) {
1902 -               printerr(1, "prepare_krb5_rfc1964_buffer: "
1903 -                           "overriding heimdal keytype (%d => %d)\n",
1904 -                           lctx->rfc1964_kd.ctx_key.type, 4);
1905 +               printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
1906 +                        __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
1907                 lctx->rfc1964_kd.ctx_key.type = 4;
1908         }
1909  #endif
1910 -       printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
1911 -                "enctype %d and length %d\n",
1912 -                lctx->rfc1964_kd.ctx_key.type,
1913 +       printerr(2, "%s: serializing keys with enctype %d and length %d\n",
1914 +                __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
1915                  lctx->rfc1964_kd.ctx_key.length);
1916  
1917         /* derive the encryption key and copy it into buffer */
1918 @@ -152,15 +151,361 @@ out_err:
1919         return -1;
1920  }
1921  
1922 -static int
1923 -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
1924 -       gss_buffer_desc *buf)
1925 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1926 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1927 +
1928 +/* for 3DES */
1929 +#define KG_USAGE_SEAL 22
1930 +#define KG_USAGE_SIGN 23
1931 +#define KG_USAGE_SEQ  24
1932 +
1933 +/* for rfc???? */
1934 +#define KG_USAGE_ACCEPTOR_SEAL  22
1935 +#define KG_USAGE_ACCEPTOR_SIGN  23
1936 +#define KG_USAGE_INITIATOR_SEAL 24
1937 +#define KG_USAGE_INITIATOR_SIGN 25
1938 +
1939 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
1940 +enum seal_alg {
1941 +  SEAL_ALG_NONE            = 0xffff,
1942 +  SEAL_ALG_DES             = 0x0000,
1943 +  SEAL_ALG_1               = 0x0001, /* not published */
1944 +  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
1945 +  SEAL_ALG_DES3KD          = 0x0002
1946 +};
1947 +
1948 +#define KEY_USAGE_SEED_ENCRYPTION      0xAA
1949 +#define KEY_USAGE_SEED_INTEGRITY       0x55
1950 +#define KEY_USAGE_SEED_CHECKSUM                0x99
1951 +#define K5CLENGTH 5
1952 +
1953 +/* Flags for version 2 context flags */
1954 +#define KRB5_CTX_FLAG_INITIATOR                0x00000001
1955 +#define KRB5_CTX_FLAG_CFX              0x00000002
1956 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
1957 +
1958 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1959 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1960 +/*
1961 + * We don't have "legal" access to these MIT-only
1962 + * structures located in libk5crypto
1963 + */
1964 +extern void krb5int_enc_arcfour;
1965 +extern void krb5int_enc_des3;
1966 +extern void krb5int_enc_aes128;
1967 +extern void krb5int_enc_aes256;
1968 +extern int krb5_derive_key();
1969 +
1970 +static void
1971 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
1972  {
1973 -       printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
1974 -       return -1;
1975 +       memset(kout, '\0', sizeof(kout));
1976 +#ifdef HAVE_KRB5
1977 +       kout->enctype = lin->type;
1978 +       kout->length = lin->length;
1979 +       kout->contents = lin->data;
1980 +#else
1981 +       kout->keytype = lin->type;
1982 +       kout->keyvalue.length = lin->length;
1983 +       kout->keyvalue.data = lin->data;
1984 +#endif
1985  }
1986  
1987 +static void
1988 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
1989 +{
1990 +       memset(lout, '\0', sizeof(lout));
1991 +#ifdef HAVE_KRB5
1992 +       lout->type = kin->enctype;
1993 +       lout->length = kin->length;
1994 +       lout->data = kin->contents;
1995 +#else
1996 +       lout->type = kin->keytype;
1997 +       lout->length = kin->keyvalue.length;
1998 +       memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
1999 +#endif
2000 +}
2001  
2002 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2003 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2004 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2005 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2006 +/*
2007 + * Function to derive a new key from a given key and given constant data.
2008 + */
2009 +static krb5_error_code
2010 +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
2011 +                int usage, char extra)
2012 +{
2013 +       krb5_error_code code;
2014 +       unsigned char constant_data[K5CLENGTH];
2015 +       krb5_data datain;
2016 +       int keylength;
2017 +       void *enc;
2018 +       krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
2019 +#ifdef HAVE_HEIMDAL
2020 +       krb5_context kcontext;
2021 +       krb5_keyblock *outkey;
2022 +#endif
2023 +
2024 +       /*
2025 +        * XXX Hack alert.  We don't have "legal" access to these
2026 +        * values and structures located in libk5crypto
2027 +        */
2028 +       switch (in->type) {
2029 +       case ENCTYPE_DES3_CBC_SHA1:
2030 +#ifdef HAVE_KRB5
2031 +       case ENCTYPE_DES3_CBC_RAW:
2032 +#endif
2033 +               keylength = 24;
2034 +#ifdef HAVE_KRB5
2035 +               enc = &krb5int_enc_des3;
2036 +#endif
2037 +               break;
2038 +       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
2039 +               keylength = 16;
2040 +#ifdef HAVE_KRB5
2041 +               enc = &krb5int_enc_aes128;
2042 +#endif
2043 +               break;
2044 +       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
2045 +               keylength = 32;
2046 +#ifdef HAVE_KRB5
2047 +               enc = &krb5int_enc_aes256;
2048 +#endif
2049 +               break;
2050 +       default:
2051 +               code = KRB5_BAD_ENCTYPE;
2052 +               goto out;
2053 +       }
2054 +
2055 +       /* allocate memory for output key */
2056 +       if ((out->data = malloc(keylength)) == NULL) {
2057 +               code = ENOMEM;
2058 +               goto out;
2059 +       }
2060 +       out->length = keylength;
2061 +       out->type = in->type;
2062 +
2063 +       /* Convert to correct format for call to krb5_derive_key */
2064 +       key_lucid_to_krb5(in, &kin);
2065 +       key_lucid_to_krb5(out, &kout);
2066 +
2067 +       datain.data = (char *) constant_data;
2068 +       datain.length = K5CLENGTH;
2069 +
2070 +       ((char *)(datain.data))[0] = (usage>>24)&0xff;
2071 +       ((char *)(datain.data))[1] = (usage>>16)&0xff;
2072 +       ((char *)(datain.data))[2] = (usage>>8)&0xff;
2073 +       ((char *)(datain.data))[3] = usage&0xff;
2074 +
2075 +       ((char *)(datain.data))[4] = (char) extra;
2076 +
2077 +#ifdef HAVE_KRB5
2078 +       code = krb5_derive_key(enc, &kin, &kout, &datain);
2079 +#else
2080 +       if ((code = krb5_init_context(&kcontext))) {
2081 +       }
2082 +       code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
2083 +#endif
2084 +       if (code) {
2085 +               free(out->data);
2086 +               out->data = NULL;
2087 +               goto out;
2088 +       }
2089 +#ifdef HAVE_KRB5
2090 +       key_krb5_to_lucid(&kout, out);
2091 +#else
2092 +       key_krb5_to_lucid(outkey, out);
2093 +       krb5_free_keyblock(kcontext, outkey);
2094 +       krb5_free_context(kcontext);
2095 +#endif
2096 +
2097 +  out:
2098 +       if (code)
2099 +               printerr(0, "ERROR: %s: returning error %d (%s)\n",
2100 +                        __FUNCTION__, code, error_message(code));
2101 +       return (code);
2102 +}
2103 +
2104 +
2105 +/*
2106 + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
2107 + * to send to the kernel for newer encryption types -- or for DES3.
2108 + *
2109 + * The new format is:
2110 + *
2111 + *     u32 initiate;                   ( whether we are the initiator or not )
2112 + *     s32 endtime;
2113 + *     u32 flags;
2114 + *     #define KRB5_CTX_FLAG_INITIATOR         0x00000001
2115 + *     #define KRB5_CTX_FLAG_CFX               0x00000002
2116 + *     #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
2117 + *     u64 seq_send;
2118 + *     u32  enctype;                   ( encrption type of keys )
2119 + *     u32  size_of_each_key;          ( size of each key in bytes )
2120 + *     u32  number_of_keys;            ( N -- should always be 3 for now )
2121 + *     keydata-1;                      ( Ke )
2122 + *     keydata-2;                      ( Ki )
2123 + *     keydata-3;                      ( Kc )
2124 + *
2125 + */
2126 +static int
2127 +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
2128 +                           gss_buffer_desc *buf)
2129 +{
2130 +       char *p, *end;
2131 +       uint32_t v2_flags = 0;
2132 +       gss_krb5_lucid_key_t enc_key;
2133 +       gss_krb5_lucid_key_t derived_key;
2134 +       gss_buffer_desc fakeoid;
2135 +       uint32_t enctype;
2136 +       uint32_t keysize;
2137 +       uint32_t numkeys;
2138 +
2139 +       memset(&enc_key, 0, sizeof(enc_key));
2140 +       memset(&fakeoid, 0, sizeof(fakeoid));
2141 +
2142 +       if (!(buf->value = calloc(1, MAX_CTX_LEN)))
2143 +               goto out_err;
2144 +       p = buf->value;
2145 +       end = buf->value + MAX_CTX_LEN;
2146 +
2147 +       /* Version 2 */
2148 +       if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
2149 +       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
2150 +
2151 +       if (lctx->initiate)
2152 +               v2_flags |= KRB5_CTX_FLAG_INITIATOR;
2153 +       if (lctx->protocol != 0)
2154 +               v2_flags |= KRB5_CTX_FLAG_CFX;
2155 +       if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
2156 +               v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
2157 +
2158 +       if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
2159 +
2160 +       if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
2161 +
2162 +       /* Protocol 0 here implies DES3 or RC4 */
2163 +       printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
2164 +       if (lctx->protocol == 0) {
2165 +               enctype = lctx->rfc1964_kd.ctx_key.type;
2166 +#ifdef HAVE_HEIMDAL
2167 +               /*
2168 +                * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for
2169 +                * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16).
2170 +                * Force the Heimdal enctype to 6.
2171 +                */
2172 +               if (enctype == ENCTYPE_DES3_CBC_SHA1) {
2173 +                       printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
2174 +                                __FUNCTION__, enctype, 6);
2175 +
2176 +                       enctype = 6;
2177 +               }
2178 +#endif
2179 +               keysize = lctx->rfc1964_kd.ctx_key.length;
2180 +               numkeys = 3;    /* XXX is always gonna be three? */
2181 +       } else {
2182 +               if (lctx->cfx_kd.have_acceptor_subkey) {
2183 +                       enctype = lctx->cfx_kd.acceptor_subkey.type;
2184 +                       keysize = lctx->cfx_kd.acceptor_subkey.length;
2185 +               } else {
2186 +                       enctype = lctx->cfx_kd.ctx_key.type;
2187 +                       keysize = lctx->cfx_kd.ctx_key.length;
2188 +               }
2189 +               numkeys = 3;
2190 +       }
2191 +       printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
2192 +                __FUNCTION__, numkeys, enctype, keysize);
2193 +       if (WRITE_BYTES(&p, end, enctype)) goto out_err;
2194 +       if (WRITE_BYTES(&p, end, keysize)) goto out_err;
2195 +       if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
2196 +
2197 +       if (lctx->protocol == 0) {
2198 +               /* derive and send down: Ke, Ki, and Kc */
2199 +               /* Ke */
2200 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
2201 +                               lctx->rfc1964_kd.ctx_key.length))
2202 +                       goto out_err;
2203 +
2204 +               /* Ki */
2205 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
2206 +                               lctx->rfc1964_kd.ctx_key.length))
2207 +                       goto out_err;
2208 +
2209 +               /* Kc */
2210 +               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
2211 +                               &derived_key,
2212 +                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
2213 +                       goto out_err;
2214 +               if (write_bytes(&p, end, derived_key.data,
2215 +                               derived_key.length))
2216 +                       goto out_err;
2217 +               free(derived_key.data);
2218 +       } else {
2219 +               gss_krb5_lucid_key_t *keyptr;
2220 +               uint32_t sign_usage, seal_usage;
2221 +
2222 +               if (lctx->cfx_kd.have_acceptor_subkey)
2223 +                       keyptr = &lctx->cfx_kd.acceptor_subkey;
2224 +               else
2225 +                       keyptr = &lctx->cfx_kd.ctx_key;
2226 +
2227 +               if (lctx->initiate == 1) {
2228 +                       sign_usage = KG_USAGE_INITIATOR_SIGN;
2229 +                       seal_usage = KG_USAGE_INITIATOR_SEAL;
2230 +               } else {
2231 +                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
2232 +                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
2233 +               }
2234 +
2235 +               /* derive and send down: Ke, Ki, and Kc */
2236 +
2237 +               /* Ke */
2238 +               if (derive_key_lucid(keyptr, &derived_key,
2239 +                              seal_usage, KEY_USAGE_SEED_ENCRYPTION))
2240 +                       goto out_err;
2241 +               if (write_bytes(&p, end, derived_key.data,
2242 +                               derived_key.length))
2243 +                       goto out_err;
2244 +               free(derived_key.data);
2245 +
2246 +               /* Ki */
2247 +               if (derive_key_lucid(keyptr, &derived_key,
2248 +                              seal_usage, KEY_USAGE_SEED_INTEGRITY))
2249 +                       goto out_err;
2250 +               if (write_bytes(&p, end, derived_key.data,
2251 +                               derived_key.length))
2252 +                       goto out_err;
2253 +               free(derived_key.data);
2254 +
2255 +               /* Kc */
2256 +               if (derive_key_lucid(keyptr, &derived_key,
2257 +                              sign_usage, KEY_USAGE_SEED_CHECKSUM))
2258 +                       goto out_err;
2259 +               if (write_bytes(&p, end, derived_key.data,
2260 +                               derived_key.length))
2261 +                       goto out_err;
2262 +               free(derived_key.data);
2263 +       }
2264 +
2265 +       buf->length = p - (char *)buf->value;
2266 +       return 0;
2267 +
2268 +out_err:
2269 +       printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
2270 +                __FUNCTION__);
2271 +       if (buf->value) {
2272 +               free(buf->value);
2273 +               buf->value = NULL;
2274 +       }
2275 +       buf->length = 0;
2276 +       if (enc_key.data) {
2277 +               free(enc_key.data);
2278 +               enc_key.data = NULL;
2279 +       }
2280 +       return -1;
2281 +}
2282  int
2283  serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
2284  {
2285 @@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2286         gss_krb5_lucid_context_v1_t *lctx = 0;
2287         int retcode = 0;
2288  
2289 -       printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
2290 +       printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
2291         maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
2292                                                 1, &return_ctx);
2293         if (maj_stat != GSS_S_COMPLETE) {
2294 @@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2295                 break;
2296         }
2297  
2298 -       /* Now lctx points to a lucid context that we can send down to kernel */
2299 -       if (lctx->protocol == 0)
2300 +        /*
2301 +        * Now lctx points to a lucid context that we can send down to kernel
2302 +        *
2303 +        * Note: we send down different information to the kernel depending
2304 +        * on the protocol version and the enctyption type.
2305 +        * For protocol version 0 with all enctypes besides DES3, we use
2306 +        * the original format.  For protocol version != 0 or DES3, we
2307 +        * send down the new style information.
2308 +        */
2309 +
2310 +       if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
2311                 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
2312         else
2313 -               retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
2314 +               retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
2315  
2316         maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
2317         if (maj_stat != GSS_S_COMPLETE) {
2318 @@ -206,8 +560,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2319         }
2320  
2321         if (retcode) {
2322 -               printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
2323 -                        "failed (retcode = %d)\n", retcode);
2324 +               printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
2325 +                        __FUNCTION__, retcode);
2326                 goto out_err;
2327         }
2328  
2329 @@ -217,4 +571,7 @@ out_err:
2330         printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
2331         return -1;
2332  }
2333 +
2334 +
2335 +
2336  #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
2337 diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c
2338 --- nfs-utils-1.0.11/utils/gssd/context_mit.c~CITI_NFS4_ALL     2007-02-26 18:52:22.399022000 -0500
2339 +++ nfs-utils-1.0.11-kwc/utils/gssd/context_mit.c       2007-02-26 18:52:22.561859000 -0500
2340 @@ -1,5 +1,5 @@
2341  /*
2342 -  Copyright (c) 2004 The Regents of the University of Michigan.
2343 +  Copyright (c) 2004-2006 The Regents of the University of Michigan.
2344    All rights reserved.
2345  
2346    Redistribution and use in source and binary forms, with or without
2347 @@ -36,6 +36,7 @@
2348  #include <stdio.h>
2349  #include <syslog.h>
2350  #include <string.h>
2351 +#include <errno.h>
2352  #include <gssapi/gssapi.h>
2353  #include <rpc/rpc.h>
2354  #include <rpc/auth_gss.h>
2355 @@ -50,8 +51,7 @@
2356  /* XXX argggg, there's gotta be a better way than just duplicating this
2357   * whole struct.  Unfortunately, this is in a "private" header file,
2358   * so this is our best choice at this point :-/
2359 - *
2360 - * XXX Does this match the Heimdal definition?  */
2361 + */
2362  
2363  typedef struct _krb5_gss_ctx_id_rec {
2364     unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
2365 @@ -139,6 +139,124 @@ write_keyblock(char **p, char *end, stru
2366  }
2367  
2368  /*
2369 + * XXX Hack alert! XXX Do NOT submit upstream!
2370 + * XXX Hack alert! XXX Do NOT submit upstream!
2371 + *
2372 + * We shouldn't be using these definitions
2373 + *
2374 + * XXX Hack alert! XXX Do NOT submit upstream!
2375 + * XXX Hack alert! XXX Do NOT submit upstream!
2376 + */
2377 +/* for 3DES */
2378 +#define KG_USAGE_SEAL 22
2379 +#define KG_USAGE_SIGN 23
2380 +#define KG_USAGE_SEQ  24
2381 +
2382 +/* for rfc???? */
2383 +#define KG_USAGE_ACCEPTOR_SEAL  22
2384 +#define KG_USAGE_ACCEPTOR_SIGN  23
2385 +#define KG_USAGE_INITIATOR_SEAL 24
2386 +#define KG_USAGE_INITIATOR_SIGN 25
2387 +
2388 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
2389 +enum seal_alg {
2390 +  SEAL_ALG_NONE            = 0xffff,
2391 +  SEAL_ALG_DES             = 0x0000,
2392 +  SEAL_ALG_1               = 0x0001, /* not published */
2393 +  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
2394 +  SEAL_ALG_DES3KD          = 0x0002
2395 +};
2396 +
2397 +#define KEY_USAGE_SEED_ENCRYPTION      0xAA
2398 +#define KEY_USAGE_SEED_INTEGRITY       0x55
2399 +#define KEY_USAGE_SEED_CHECKSUM                0x99
2400 +#define K5CLENGTH 5
2401 +
2402 +extern void krb5_enc_des3;
2403 +extern void krb5int_enc_des3;
2404 +extern void krb5int_enc_arcfour;
2405 +extern void krb5int_enc_aes128;
2406 +extern void krb5int_enc_aes256;
2407 +extern int krb5_derive_key();
2408 +
2409 +/*
2410 + * XXX Hack alert! XXX Do NOT submit upstream!
2411 + * XXX Hack alert! XXX Do NOT submit upstream!
2412 + *
2413 + * We should be passing down a single key to the kernel
2414 + * and it should be deriving the other keys.  We cannot
2415 + * depend on any of this stuff being accessible in the
2416 + * future.
2417 + *
2418 + * XXX Hack alert! XXX Do NOT submit upstream!
2419 + * XXX Hack alert! XXX Do NOT submit upstream!
2420 + */
2421 +/*
2422 + * Function to derive a new key from a given key and given constant data.
2423 + */
2424 +static krb5_error_code
2425 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
2426 +{
2427 +       krb5_error_code code;
2428 +       unsigned char constant_data[K5CLENGTH];
2429 +       krb5_data datain;
2430 +       int keylength;
2431 +       void *enc;
2432 +
2433 +       switch (in->enctype) {
2434 +#ifdef ENCTYPE_DES3_CBC_RAW
2435 +       case ENCTYPE_DES3_CBC_RAW:
2436 +               keylength = 24;
2437 +/* Extra hack, the structure was renamed as rc4 was added... */
2438 +#if defined(ENCTYPE_ARCFOUR_HMAC)
2439 +               enc = &krb5int_enc_des3;
2440 +#else
2441 +               enc = &krb5_enc_des3;
2442 +#endif
2443 +               break;
2444 +#endif
2445 +#ifdef ENCTYPE_ARCFOUR_HMAC
2446 +       case ENCTYPE_ARCFOUR_HMAC:
2447 +               keylength = 16;
2448 +               enc = &krb5int_enc_arcfour;
2449 +               break;
2450 +#endif
2451 +       default:
2452 +               code = KRB5_BAD_ENCTYPE;
2453 +               goto out;
2454 +       }
2455 +
2456 +       /* allocate memory for output key */
2457 +       if ((out->contents = malloc(keylength)) == NULL) {
2458 +               code = ENOMEM;
2459 +               goto out;
2460 +       }
2461 +       out->length = keylength;
2462 +       out->enctype = in->enctype;
2463 +
2464 +       datain.data = (char *) constant_data;
2465 +       datain.length = K5CLENGTH;
2466 +
2467 +       datain.data[0] = (usage>>24)&0xff;
2468 +       datain.data[1] = (usage>>16)&0xff;
2469 +       datain.data[2] = (usage>>8)&0xff;
2470 +       datain.data[3] = usage&0xff;
2471 +
2472 +       datain.data[4] = (char) extra;
2473 +
2474 +       if ((code = krb5_derive_key(enc, in, out, &datain))) {
2475 +               free(out->contents);
2476 +               out->contents = NULL;
2477 +       }
2478 +
2479 +  out:
2480 +       if (code)
2481 +               printerr(0, "ERROR: derive_key returning error %d (%s)\n",
2482 +                        code, error_message(code));
2483 +       return (code);
2484 +}
2485 +
2486 +/*
2487   * We really shouldn't know about glue-layer context structure, but
2488   * we need to get at the real krb5 context pointer.  This should be
2489   * removed as soon as we say there is no support for MIT Kerberos
2490 @@ -154,48 +272,124 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2491  {
2492         krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
2493         char *p, *end;
2494 -       static int constant_one = 1;
2495         static int constant_zero = 0;
2496 +       static int constant_one = 1;
2497 +       static int constant_two = 2;
2498         uint32_t word_seq_send;
2499 +       u_int64_t seq_send_64bit;
2500 +       uint32_t v2_flags = 0;
2501 +       krb5_keyblock derived_key;
2502 +       uint32_t numkeys;
2503  
2504         if (!(buf->value = calloc(1, MAX_CTX_LEN)))
2505                 goto out_err;
2506         p = buf->value;
2507         end = buf->value + MAX_CTX_LEN;
2508  
2509 -       if (kctx->initiate) {
2510 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2511 -       }
2512 -       else {
2513 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2514 -       }
2515 -       if (kctx->seed_init) {
2516 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2517 -       }
2518 -       else {
2519 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2520 -       }
2521 -       if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
2522 +       switch (kctx->sealalg) {
2523 +       case SEAL_ALG_DES:
2524 +               /* Old format of context to the kernel */
2525 +               if (kctx->initiate) {
2526 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2527 +               }
2528 +               else {
2529 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2530 +               }
2531 +               if (kctx->seed_init) {
2532 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2533 +               }
2534 +               else {
2535 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2536 +               }
2537 +               if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
2538 +                       goto out_err;
2539 +               if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
2540 +               if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
2541 +               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2542 +               word_seq_send = kctx->seq_send;
2543 +               if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
2544 +               if (write_oid(&p, end, kctx->mech_used)) goto out_err;
2545 +
2546 +               printerr(2, "serialize_krb5_ctx: serializing keys with "
2547 +                        "enctype %d and length %d\n",
2548 +                        kctx->enc->enctype, kctx->enc->length);
2549 +
2550 +               if (write_keyblock(&p, end, kctx->enc)) goto out_err;
2551 +               if (write_keyblock(&p, end, kctx->seq)) goto out_err;
2552 +               break;
2553 +       case SEAL_ALG_MICROSOFT_RC4:
2554 +       case SEAL_ALG_DES3KD:
2555 +               /* New format of context to the kernel */
2556 +               /* s32 endtime;
2557 +                * u32 flags;
2558 +                * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
2559 +                * #define KRB5_CTX_FLAG_CFX              0x00000002
2560 +                * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
2561 +                * u64 seq_send;
2562 +                * u32  enctype;
2563 +                * u32  size_of_each_key;    (  size in bytes )
2564 +                * u32  number_of_keys;      (  N (assumed to be 3 for now) )
2565 +                * keydata-1;                (  Ke  (Kenc for DES3) )
2566 +                * keydata-2;                (  Ki  (Kseq for DES3) )
2567 +                * keydata-3;                (  Kc (derived checksum key) )
2568 +                */
2569 +               if (kctx->initiate) {
2570 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2571 +               }
2572 +               else {
2573 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2574 +               }
2575 +               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2576 +
2577 +               /* Only applicable flag for this is initiator */
2578 +               if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
2579 +               if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
2580 +
2581 +               seq_send_64bit = kctx->seq_send;
2582 +               if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
2583 +
2584 +               if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
2585 +               if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
2586 +               numkeys = 3;
2587 +               if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
2588 +               printerr(2, "serialize_krb5_ctx: serializing %d keys with "
2589 +                        "enctype %d and size %d\n",
2590 +                        numkeys, kctx->enc->enctype, kctx->enc->length);
2591 +
2592 +               /* Ke */
2593 +               if (write_bytes(&p, end, kctx->enc->contents,
2594 +                               kctx->enc->length))
2595 +                       goto out_err;
2596 +
2597 +               /* Ki */
2598 +               if (write_bytes(&p, end, kctx->enc->contents,
2599 +                               kctx->enc->length))
2600 +                       goto out_err;
2601 +
2602 +               /* Kc */
2603 +               if (derive_key(kctx->seq, &derived_key,
2604 +                              KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
2605 +                       goto out_err;
2606 +               if (write_bytes(&p, end, derived_key.contents,
2607 +                               derived_key.length))
2608 +                       goto out_err;
2609 +               free(derived_key.contents);
2610 +               break;
2611 +       default:
2612 +               printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
2613 +                        "algorithm %d\n", kctx->sealalg);
2614                 goto out_err;
2615 -       if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
2616 -       if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
2617 -       if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2618 -       word_seq_send = kctx->seq_send;
2619 -       if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
2620 -       if (write_oid(&p, end, kctx->mech_used)) goto out_err;
2621 -
2622 -       printerr(2, "serialize_krb5_ctx: serializing keys with "
2623 -                "enctype %d and length %d\n",
2624 -                kctx->enc->enctype, kctx->enc->length);
2625 -
2626 -       if (write_keyblock(&p, end, kctx->enc)) goto out_err;
2627 -       if (write_keyblock(&p, end, kctx->seq)) goto out_err;
2628 +       }
2629  
2630         buf->length = p - (char *)buf->value;
2631         return 0;
2632 +
2633  out_err:
2634         printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
2635 -       if (buf->value) free(buf->value);
2636 +       if (buf->value) {
2637 +               free(buf->value);
2638 +       }
2639 +       buf->value = NULL;
2640         buf->length = 0;
2641         return -1;
2642  }
This page took 0.218905 seconds and 3 git commands to generate.