]> git.pld-linux.org Git - packages/nfs-utils.git/blob - nfs-utils-CITI_NFS4.patch
- ability to select which NFS version to serve
[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/Makefile.am~CITI_NFS4_ALL utils/mount/Makefile.am
758 --- nfs-utils-1.0.11/utils/mount/Makefile.am~CITI_NFS4_ALL      2007-02-26 18:52:10.207463000 -0500
759 +++ nfs-utils-1.0.11-kwc/utils/mount/Makefile.am        2007-02-26 18:52:17.352299000 -0500
760 @@ -1,5 +1,7 @@
761  ## Process this file with automake to produce Makefile.in
762  
763 +abs_sbindir = /sbin
764 +
765  man8_MANS      = mount.nfs.man umount.nfs.man
766  
767  sbin_PROGRAMS  = mount.nfs
768 @@ -13,13 +15,14 @@ mount_nfs_LDADD = ../../support/nfs/libn
769  MAINTAINERCLEANFILES = Makefile.in
770  
771  install-exec-hook:
772 -       (cd $(DESTDIR)$(sbindir) && \
773 -         ln -sf $(sbin_PROGRAMS) mount.nfs4 && \
774 -         ln -sf $(sbin_PROGRAMS) umount.nfs && \
775 -         ln -sf $(sbin_PROGRAMS) umount.nfs4)
776 +       (chmod +s $(sbin_PROGRAMS) && \
777 +         ln -fs $(DESTDIR)$(sbindir)/mount.nfs $(abs_sbindir)/mount.nfs && \
778 +         ln -fs $(DESTDIR)$(sbindir)/mount.nfs $(abs_sbindir)/umount.nfs && \
779 +         ln -fs $(DESTDIR)$(sbindir)/mount.nfs $(abs_sbindir)/mount.nfs4 && \
780 +         ln -fs $(DESTDIR)$(sbindir)/mount.nfs $(abs_sbindir)/umount.nfs4 )
781  uninstall-hook:
782 -       (cd $(DESTDIR)$(sbindir) && \
783 -           rm -f mount.nfs4 umount.nfs umount.nfs4)
784 +       (cd $(abs_sbindir) && \
785 +           rm -f mount.nfs umount.nfs mount.nfs4 umount.nfs4)
786  
787  
788  install-man-links:
789 diff -puN utils/mount/mount.c~CITI_NFS4_ALL utils/mount/mount.c
790 --- nfs-utils-1.0.11/utils/mount/mount.c~CITI_NFS4_ALL  2007-02-26 18:52:10.515323000 -0500
791 +++ nfs-utils-1.0.11-kwc/utils/mount/mount.c    2007-02-26 18:52:16.671458000 -0500
792 @@ -28,6 +28,7 @@
793  #include <sys/mount.h>
794  #include <getopt.h>
795  #include <mntent.h>
796 +#include <pwd.h>
797  
798  #include "fstab.h"
799  #include "xcommon.h"
800 @@ -43,6 +44,7 @@ char *progname;
801  int nomtab;
802  int verbose;
803  int mounttype;
804 +int sloppy;
805  
806  static struct option longopts[] = {
807    { "fake", 0, 0, 'f' },
808 @@ -74,6 +76,12 @@ struct opt_map {
809    int  mask;                    /* flag mask value */
810  };
811  
812 +/* Custom mount options for our own purposes.  */
813 +/* Maybe these should now be freed for kernel use again */
814 +#define MS_DUMMY       0x00000000
815 +#define MS_USERS       0x40000000
816 +#define MS_USER                0x20000000
817 +
818  static const struct opt_map opt_map[] = {
819    { "defaults", 0, 0, 0         },      /* default options */
820    { "ro",       1, 0, MS_RDONLY },      /* read-only */
821 @@ -90,6 +98,18 @@ static const struct opt_map opt_map[] = 
822    { "remount",  0, 0, MS_REMOUNT},      /* Alter flags of mounted FS */
823    { "bind",     0, 0, MS_BIND   },      /* Remount part of tree elsewhere */
824    { "rbind",    0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
825 +  { "auto",     0, 0, MS_DUMMY },       /* Can be mounted using -a */
826 +  { "noauto",   0, 0, MS_DUMMY },       /* Can  only be mounted explicitly */
827 +  { "users",    0, 0, MS_USERS  },      /* Allow ordinary user to mount */
828 +  { "nousers",  0, 1, MS_USERS  },      /* Forbid ordinary user to mount */
829 +  { "user",     0, 0, MS_USER   },      /* Allow ordinary user to mount */
830 +  { "nouser",   0, 1, MS_USER   },      /* Forbid ordinary user to mount */
831 +  { "owner",    0, 0, MS_DUMMY  },      /* Let the owner of the device mount */
832 +  { "noowner",  0, 0, MS_DUMMY  },      /* Device owner has no special privs */
833 +  { "group",    0, 0, MS_DUMMY  },      /* Let the group of the device mount */
834 +  { "nogroup",  0, 0, MS_DUMMY  },      /* Device group has no special privs */
835 +  { "_netdev",  0, 0, MS_DUMMY},        /* Device requires network */
836 +  { "comment",  0, 0, MS_DUMMY},        /* fstab comment only (kudzu,_netdev)*/
837  
838    /* add new options here */
839  #ifdef MS_NOSUB
840 @@ -104,6 +124,7 @@ static const struct opt_map opt_map[] = 
841    { "mand",     0, 0, MS_MANDLOCK },    /* Allow mandatory locks on this FS */
842    { "nomand",   0, 1, MS_MANDLOCK },    /* Forbid mandatory locks on this FS */
843  #endif
844 +  { "loop",     1, 0, MS_DUMMY   },      /* use a loop device */
845  #ifdef MS_NOATIME
846    { "atime",    0, 1, MS_NOATIME },     /* Update access time */
847    { "noatime",  0, 0, MS_NOATIME },     /* Do not update access time */
848 @@ -121,6 +142,12 @@ static char * fix_opts_string (int flags
849         char *new_opts;
850  
851         new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
852 +       if (flags & MS_USER) {
853 +               struct passwd *pw = getpwuid(getuid());
854 +               if(pw)
855 +                       new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name);
856 +       }
857 +       
858         for (om = opt_map; om->opt != NULL; om++) {
859                 if (om->skip)
860                         continue;
861 @@ -132,22 +159,54 @@ static char * fix_opts_string (int flags
862         if (extra_opts && *extra_opts) {
863                 new_opts = xstrconcat3(new_opts, ",", extra_opts);
864         }
865 +
866         return new_opts;
867  }
868  
869 +static inline void dup_mntent(struct mntent *ment, nfs_mntent_t *nment)
870 +{
871 +       /* Not sure why nfs_mntent_t should exist */
872 +       nment->mnt_fsname = strdup(ment->mnt_fsname);
873 +       nment->mnt_dir = strdup(ment->mnt_dir);
874 +       nment->mnt_type = strdup(ment->mnt_type);
875 +       nment->mnt_opts = strdup(ment->mnt_opts);
876 +       nment->mnt_freq = ment->mnt_freq;
877 +       nment->mnt_passno = ment->mnt_passno;
878 +}
879 +static inline void 
880 +free_mntent(nfs_mntent_t *ment, int remount)
881 +{
882 +       free(ment->mnt_fsname);
883 +       free(ment->mnt_dir);
884 +       free(ment->mnt_type);
885 +       /* 
886 +        * Note: free(ment->mnt_opts) happens in discard_mntentchn()
887 +        * via update_mtab() on remouts
888 +        */
889 +        if (!remount)
890 +               free(ment->mnt_opts);
891 +}
892  
893  int add_mtab(char *fsname, char *mount_point, char *fstype, int flags, char *opts, int freq, int passno)
894  {
895         struct mntent ment;
896 -       int fd;
897         FILE *mtab;
898  
899         ment.mnt_fsname = fsname;
900         ment.mnt_dir = mount_point;
901         ment.mnt_type = fstype;
902         ment.mnt_opts = fix_opts_string(flags, opts);
903 -       ment.mnt_freq = 0;
904 -       ment.mnt_passno= 0;
905 +       ment.mnt_freq = freq;
906 +       ment.mnt_passno= passno;
907 +
908 +       if(flags & MS_REMOUNT) {
909 +               nfs_mntent_t nment;
910 +               
911 +               dup_mntent(&ment, &nment);
912 +               update_mtab(nment.mnt_dir, &nment);
913 +               free_mntent(&nment, 1);
914 +               return 0;
915 +       }
916  
917         lock_mtab();
918  
919 @@ -191,6 +250,7 @@ void mount_usage()
920         printf("\t-w\t\tMount file system read-write\n");
921         printf("\t-f\t\tFake mount, don't actually mount\n");
922         printf("\t-n\t\tDo not update /etc/mtab\n");
923 +       printf("\t-s\t\tTolerate sloppy mount options rather than failing.\n");
924         printf("\t-h\t\tPrint this help\n");
925         printf("\tversion\t\tnfs4 - NFS version 4, nfs - older NFS version supported\n");
926         printf("\tnfsoptions\tRefer mount.nfs(8) or nfs(5)\n\n");
927 @@ -225,52 +285,98 @@ static void parse_opts (const char *opti
928  {
929         if (options != NULL) {
930                 char *opts = xstrdup(options);
931 -               char *opt;
932 -               int len = strlen(opts) + 20;
933 -
934 +               char *opt, *p;
935 +               int len = strlen(opts) + 256;
936 +               int open_quote = 0;
937
938                 *extra_opts = xmalloc(len);
939                 **extra_opts = '\0';
940  
941 -               for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
942 -                       parse_opt(opt, flags, *extra_opts, len);
943 -
944 +               for (p=opts, opt=NULL; p && *p; p++) {
945 +                       if (!opt)
946 +                               opt = p;                /* begin of the option item */
947 +                       if (*p == '"') 
948 +                               open_quote ^= 1;        /* reverse the status */
949 +                       if (open_quote)
950 +                               continue;               /* still in quoted block */
951 +                       if (*p == ',')
952 +                               *p = '\0';              /* terminate the option item */
953 +                       /* end of option item or last item */
954 +                       if (*p == '\0' || *(p+1) == '\0') {
955 +                               parse_opt(opt, flags, *extra_opts, len);
956 +                               opt = NULL;
957 +                       }
958 +               } 
959                 free(opts);
960         }
961 +}
962  
963 +/*
964 + * Look for an option in a comma-separated list
965 + */
966 +int
967 +contains(const char *list, const char *s) {
968 +       int n = strlen(s);
969 +
970 +       while (*list) {
971 +               if (strncmp(list, s, n) == 0 &&
972 +                 (list[n] == 0 || list[n] == ','))
973 +                       return 1;
974 +               while (*list && *list++ != ',') ;
975 +       }
976 +       return 0;
977 +}
978 +
979 +/*
980 + * If list contains "user=peter" and we ask for "user=", return "peter"
981 + */
982 +char *
983 +get_value(const char *list, const char *s) {
984 +       const char *t;
985 +       int n = strlen(s);
986 +
987 +       while (*list) {
988 +               if (strncmp(list, s, n) == 0) {
989 +                       s = t = list+n;
990 +                       while (*s && *s != ',')
991 +                               s++;
992 +                       return xstrndup(t, s-t);
993 +               }
994 +               while (*list && *list++ != ',') ;
995 +       }
996 +       return 0;
997  }
998  
999  static void mount_error(char *node)
1000  {
1001         switch(errno) {
1002                 case ENOTDIR:
1003 -                       printf("%s: mount point %s is not a directory\n", progname, node);
1004 +                       fprintf(stderr, "%s: mount point %s is not a directory\n", progname, node);
1005                         break;
1006                 case EBUSY:
1007 -                       printf("%s: %s is already mounted or busy\n", progname, node);
1008 +                       fprintf(stderr, "%s: %s is already mounted or busy\n", progname, node);
1009                         break;
1010                 case ENOENT:
1011 -                       printf("%s: mount point %s does not exist\n", progname, node);
1012 +                       fprintf(stderr, "%s: mount point %s does not exist\n", progname, node);
1013                         break;
1014                 default:
1015 -                       printf("%s: %s\n", progname, strerror(errno));
1016 +                       fprintf(stderr, "%s: %s\n", progname, strerror(errno));
1017         }
1018  }
1019 +#define NFS_MOUNT_VERS_DEFAULT 3
1020  
1021  int main(int argc, char *argv[])
1022  {
1023 -       int c, flags = 0, nfs_mount_vers = 0, mnt_err = 1, fake = 0;
1024 +       int c, flags = 0, nfs_mount_vers, mnt_err = 1, fake = 0;
1025         char *spec, *mount_point, *extra_opts = NULL;
1026         char *mount_opts = NULL, *p;
1027 +       struct mntentchn *mc;
1028 +       uid_t uid = getuid();
1029  
1030         progname = argv[0];
1031         if ((p = strrchr(progname, '/')) != NULL)
1032                 progname = p+1;
1033  
1034 -       if (getuid() != 0) {
1035 -               printf("%s: only root can do that.\n", progname);
1036 -               exit(1);
1037 -       }
1038 -
1039         if(!strncmp(progname, "umount", strlen("umount"))) {
1040                 if(argc < 2) {
1041                         umount_usage();
1042 @@ -292,7 +398,11 @@ int main(int argc, char *argv[])
1043                 return 0;
1044         }
1045  
1046 -       while ((c = getopt_long (argc - 2, argv + 2, "rt:vVwfno:h",
1047 +       nfs_mount_vers = NFS_MOUNT_VERS_DEFAULT;
1048 +       if (!strcmp(progname, "mount.nfs4"))
1049 +               nfs_mount_vers = 4;
1050 +
1051 +       while ((c = getopt_long (argc - 2, argv + 2, "rt:vVwfno:hs",
1052                                 longopts, NULL)) != -1) {
1053                 switch (c) {
1054                 case 'r':
1055 @@ -322,6 +432,9 @@ int main(int argc, char *argv[])
1056                         else
1057                                 mount_opts = xstrdup(optarg);
1058                         break;
1059 +               case 's':
1060 +                       ++sloppy;
1061 +                       break;
1062                 case 128: /* bind */
1063                         mounttype = MS_BIND;
1064                         break;
1065 @@ -352,31 +465,59 @@ int main(int argc, char *argv[])
1066  
1067         spec = argv[1];
1068         mount_point = canonicalize(argv[2]);
1069 -       
1070 +
1071         parse_opts(mount_opts, &flags, &extra_opts);
1072  
1073 -       if (!strcmp(progname, "mount.nfs4") || nfs_mount_vers == 4) {
1074 -               nfs_mount_vers = 4;
1075 -               mnt_err = nfs4mount(spec, mount_point, &flags, &extra_opts, &mount_opts, 0);
1076 +       if (uid != 0 && !(flags & MS_USERS) && !(flags & MS_USER)) {
1077 +               fprintf(stderr, "%s: permission denied\n", progname);
1078 +               exit(1);
1079 +       }
1080 +
1081 +       if ((flags & MS_USER || flags & MS_USERS) && uid != 0) {
1082 +               /* check if fstab has entry, and further see if the user or users option is given */
1083 +               if ((mc = getfsspec(spec)) == NULL &&
1084 +                   (mc = getfsfile(spec)) == NULL) {
1085 +                       fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1086 +                       exit(1);
1087 +               }
1088 +               else {
1089 +                       if((flags & MS_USER) && !contains(mc->m.mnt_opts, "user")) {
1090 +                               fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1091 +                               exit(1);
1092 +                       }
1093 +                       if((flags & MS_USERS) && !contains(mc->m.mnt_opts, "users")) {
1094 +                               fprintf(stderr, "%s: permission denied - invalid option\n", progname);
1095 +                               exit(1);
1096 +                       }
1097 +               }
1098 +       }
1099 +
1100 +       if (nfs_mount_vers == 4) {
1101 +               mnt_err = nfs4mount(spec, mount_point, &flags, 
1102 +                       &extra_opts, &mount_opts, 0);
1103         }
1104         else {
1105                 if (!strcmp(progname, "mount.nfs")) {
1106                         mnt_err = nfsmount(spec, mount_point, &flags,
1107 -                                       &extra_opts, &mount_opts, &nfs_mount_vers, 0);
1108 +                                       &extra_opts, &mount_opts,  0);
1109                 }
1110         }
1111 +       if (fake)
1112 +               return 0;
1113 +       if (mnt_err)
1114 +               exit(EX_FAIL);
1115  
1116 -       if (!mnt_err && !fake) {
1117 -               mnt_err = do_mount_syscall(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
1118 -               
1119 -               if(mnt_err) {
1120 -                       mount_error(mount_point);
1121 -                       exit(-1);
1122 -               }
1123 +       mnt_err = do_mount_syscall(spec, mount_point,
1124 +                       nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
1125 +
1126 +       if(mnt_err) {
1127 +               mount_error(mount_point);
1128 +               exit(EX_FAIL);
1129 +       }
1130  
1131 -               if(!nomtab)
1132 -                       add_mtab(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs",
1133 -                                flags, extra_opts, 0, 0);
1134 +       if(!nomtab) {
1135 +               add_mtab(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs",
1136 +                        flags, extra_opts, 0, 0);
1137         }
1138  
1139         return 0;
1140 diff -puN utils/mount/nfs_mount.h~CITI_NFS4_ALL utils/mount/nfs_mount.h
1141 --- nfs-utils-1.0.11/utils/mount/nfs_mount.h~CITI_NFS4_ALL      2007-02-26 18:52:10.854011000 -0500
1142 +++ nfs-utils-1.0.11-kwc/utils/mount/nfs_mount.h        2007-02-26 18:52:14.652380000 -0500
1143 @@ -78,7 +78,9 @@ struct nfs_mount_data {
1144  #define AUTH_GSS_SPKMP         390011
1145  #endif
1146  
1147 -int nfsmount(const char *, const char *, int *, char **, char **, int *, int);
1148 +int nfsmount(const char *, const char *, int *, char **, char **, int);
1149  void mount_errors(char *, int, int);
1150 +int contains(const char *, const char *);
1151 +char *get_value(const char *, const char *);
1152  
1153  #endif /* _NFS_MOUNT_H */
1154 diff -puN utils/mount/nfsumount.c~CITI_NFS4_ALL utils/mount/nfsumount.c
1155 --- nfs-utils-1.0.11/utils/mount/nfsumount.c~CITI_NFS4_ALL      2007-02-26 18:52:11.207011000 -0500
1156 +++ nfs-utils-1.0.11-kwc/utils/mount/nfsumount.c        2007-02-26 18:52:16.013751000 -0500
1157 @@ -19,16 +19,19 @@
1158  
1159  #include <stdio.h>
1160  #include <errno.h>
1161 +#include <unistd.h>
1162  #include <getopt.h>
1163  #include <mntent.h>
1164  #include <sys/mount.h>
1165  #include <ctype.h>
1166 +#include <pwd.h>
1167  
1168  #include "xcommon.h"
1169  #include "fstab.h"
1170  #include "nls.h"
1171  #include "conn.h"
1172  
1173 +#include "nfs_mount.h"
1174  #include "mount_constants.h"
1175  #include "mount.h"
1176  #include "nfsumount.h"
1177 @@ -98,9 +101,9 @@ int nfs_call_umount(clnt_addr_t *mnt_ser
1178         }
1179         mnt_closeclnt(clnt, msock);
1180         if (res == RPC_SUCCESS)
1181 -               return 1;
1182 +               return 0;
1183   out_bad:
1184 -       return 0;
1185 +       return 1;
1186  }
1187  
1188  u_int get_mntproto(const char *);
1189 @@ -249,9 +252,6 @@ int add_mtab2(const char *spec, const ch
1190          return 1;
1191  }
1192  
1193 -/*
1194 - * Returns 1 if everything went well, else 0.
1195 - */
1196  int _nfsumount(const char *spec, const char *opts)
1197  {
1198         char *hostname;
1199 @@ -307,8 +307,8 @@ int _nfsumount(const char *spec, const c
1200                 goto out_bad;
1201         return nfs_call_umount(&mnt_server, &dirname);
1202   out_bad:
1203 -       printf("%s: %s: not found or not mounted\n", progname, spec);
1204 -       return 0;
1205 +       fprintf(stderr, "%s: %s: not found / mounted or server not reachable\n", progname, spec);
1206 +       return 1;
1207  }
1208  
1209  static struct option umount_longopts[] =
1210 @@ -334,7 +334,7 @@ void umount_usage()
1211  
1212  int nfsumount(int argc, char *argv[])
1213  {
1214 -       int c, ret;
1215 +       int c, ret, v4=0;
1216         char *spec;
1217         struct mntentchn *mc;
1218  
1219 @@ -372,20 +372,33 @@ int nfsumount(int argc, char *argv[])
1220         mc = getmntdirbackward(spec, NULL);
1221         if (!mc)
1222                 mc = getmntdevbackward(spec, NULL);
1223 -       if (!mc && verbose)
1224 -               printf(_("Could not find %s in mtab\n"), spec);
1225 -
1226 -       if(mc) {
1227 -               ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
1228 -               if(ret)
1229 -                       ret = add_mtab2(mc->m.mnt_fsname, mc->m.mnt_dir,
1230 -                               mc->m.mnt_type, mc->m.mnt_opts, mc);
1231 +       if (mc == NULL) {
1232 +               fprintf(stderr, "%s: Unable to find '%s' in mount table\n",
1233 +                               progname, spec);
1234 +               exit(1);
1235         }
1236 -       else {
1237 -               ret = _nfsumount(spec, NULL);
1238 -               if(ret)
1239 -                       ret = add_mtab2(spec, spec, spec, spec, NULL);
1240 +       if(contains(mc->m.mnt_opts, "user") && getuid() != 0) {
1241 +               struct passwd *pw = getpwuid(getuid());
1242 +               if(!pw || strcmp(pw->pw_name, get_value(mc->m.mnt_opts, "user="))) {
1243 +                       fprintf(stderr, "%s: permission denied to unmount %s\n",
1244 +                                       progname, spec);
1245 +                       exit(1);
1246 +               }
1247 +       } else {
1248 +               if(!contains(mc->m.mnt_opts, "users") && getuid() != 0) {
1249 +                       fprintf(stderr, "%s: only root can unmount %s from %s\n",
1250 +                                       progname, mc->m.mnt_fsname, mc->m.mnt_dir);
1251 +                       exit(1);
1252 +               }
1253         }
1254 +       v4 = contains(mc->m.mnt_type, "nfs4");
1255 +
1256 +       ret = 0;
1257 +       if(!force && !lazy && !v4)
1258 +               ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
1259 +       if(!ret)
1260 +               ret = add_mtab2(mc->m.mnt_fsname, mc->m.mnt_dir,
1261 +                       mc->m.mnt_type, mc->m.mnt_opts, mc);
1262  
1263         return(ret);
1264  }
1265 diff -puN utils/mount/nfs4mount.c~CITI_NFS4_ALL utils/mount/nfs4mount.c
1266 --- nfs-utils-1.0.11/utils/mount/nfs4mount.c~CITI_NFS4_ALL      2007-02-26 18:52:12.678257000 -0500
1267 +++ nfs-utils-1.0.11-kwc/utils/mount/nfs4mount.c        2007-02-26 18:52:13.199107000 -0500
1268 @@ -50,6 +50,7 @@
1269  #endif
1270  
1271  extern int verbose;
1272 +extern int sloppy;
1273  
1274  char *IDMAPLCK = DEFAULT_DIR "/rpcidmapd";
1275  #define idmapd_check() do { \
1276 @@ -335,7 +336,7 @@ int nfs4mount(const char *spec, const ch
1277                                 nocto = !val;
1278                         else if (!strcmp(opt, "ac"))
1279                                 noac = !val;
1280 -                       else {
1281 +                       else if (!sloppy) {
1282                                 printf(_("unknown nfs mount option: "
1283                                          "%s%s\n"), val ? "" : "no", opt);
1284                                 goto fail;
1285 diff -puN utils/mount/nfsmount.c~CITI_NFS4_ALL utils/mount/nfsmount.c
1286 --- nfs-utils-1.0.11/utils/mount/nfsmount.c~CITI_NFS4_ALL       2007-02-26 18:52:13.028107000 -0500
1287 +++ nfs-utils-1.0.11-kwc/utils/mount/nfsmount.c 2007-02-26 18:52:16.886299000 -0500
1288 @@ -104,6 +104,7 @@ typedef union {
1289  static char errbuf[BUFSIZ];
1290  static char *erreob = &errbuf[BUFSIZ];
1291  extern int verbose;
1292 +extern int sloppy;
1293  
1294  /* Convert RPC errors into strings */
1295  int rpc_strerror(int);
1296 @@ -547,15 +548,31 @@ parse_options(char *old_opts, struct nfs
1297         struct pmap *mnt_pmap = &mnt_server->pmap;
1298         struct pmap *nfs_pmap = &nfs_server->pmap;
1299         int len;
1300 -       char *opt, *opteq;
1301 +       char *opt, *opteq, *p, *opt_b;
1302         char *mounthost = NULL;
1303         char cbuf[128];
1304 +       int open_quote = 0;
1305  
1306         data->flags = 0;
1307         *bg = 0;
1308  
1309         len = strlen(new_opts);
1310 -       for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
1311 +       for (p=old_opts, opt_b=NULL; p && *p; p++) {
1312 +               if (!opt_b)
1313 +                       opt_b = p;              /* begin of the option item */
1314 +               if (*p == '"') 
1315 +                       open_quote ^= 1;        /* reverse the status */
1316 +               if (open_quote)
1317 +                       continue;               /* still in quoted block */
1318 +               if (*p == ',')
1319 +                       *p = '\0';              /* terminate the option item */
1320 +               if (*p == '\0' || *(p+1) == '\0') {
1321 +                       opt = opt_b;            /* opt is useful now */
1322 +                       opt_b = NULL;
1323 +               }
1324 +               else
1325 +                       continue;               /* still somewhere in the option item */
1326 +
1327                 if (strlen(opt) >= sizeof(cbuf))
1328                         goto bad_parameter;
1329                 if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
1330 @@ -606,13 +623,13 @@ parse_options(char *old_opts, struct nfs
1331                         } else if (!strcmp(opt, "namlen")) {
1332                                 if (nfs_mount_version >= 2)
1333                                         data->namlen = val;
1334 -                               else
1335 +                               else if (!sloppy)
1336                                         goto bad_parameter;
1337  #endif
1338                         } else if (!strcmp(opt, "addr")) {
1339                                 /* ignore */;
1340                                 continue;
1341 -                       } else
1342 +                       } else if (!sloppy)
1343                                 goto bad_parameter;
1344                         sprintf(cbuf, "%s=%s,", opt, opteq+1);
1345                 } else if (opteq) {
1346 @@ -629,7 +646,7 @@ parse_options(char *old_opts, struct nfs
1347                                         mnt_pmap->pm_prot = IPPROTO_TCP;
1348                                         data->flags |= NFS_MOUNT_TCP;
1349  #endif
1350 -                               } else
1351 +                               } else if (!sloppy)
1352                                         goto bad_parameter;
1353  #if NFS_MOUNT_VERSION >= 5
1354                         } else if (!strcmp(opt, "sec")) {
1355 @@ -658,7 +675,7 @@ parse_options(char *old_opts, struct nfs
1356                                         data->pseudoflavor = AUTH_GSS_SPKMI;
1357                                 else if (!strcmp(secflavor, "spkm3p"))
1358                                         data->pseudoflavor = AUTH_GSS_SPKMP;
1359 -                               else {
1360 +                               else if (!sloppy) {
1361                                         printf(_("Warning: Unrecognized security flavor %s.\n"),
1362                                                 secflavor);
1363                                         goto bad_parameter;
1364 @@ -670,14 +687,24 @@ parse_options(char *old_opts, struct nfs
1365                                                    strcspn(opteq+1," \t\n\r,"));
1366                          else if (!strcmp(opt, "context")) {
1367                                 char *context = opteq + 1;
1368 +                               int ctxlen = strlen(context);
1369                                 
1370 -                               if (strlen(context) > NFS_MAX_CONTEXT_LEN) {
1371 +                               if (ctxlen > NFS_MAX_CONTEXT_LEN) {
1372                                         printf(_("context parameter exceeds limit of %d\n"),
1373                                                  NFS_MAX_CONTEXT_LEN);
1374                                         goto bad_parameter;
1375                                 }
1376 -                               strncpy(data->context, context, NFS_MAX_CONTEXT_LEN);
1377 -                       } else
1378 +                               /* The context string is in the format of
1379 +                                * "system_u:object_r:...".  We only want
1380 +                                * the context str between the quotes.
1381 +                                */
1382 +                               if (*context == '"')
1383 +                                       strncpy(data->context, context+1, 
1384 +                                                       ctxlen-2);
1385 +                               else
1386 +                                       strncpy(data->context, context, 
1387 +                                                       NFS_MAX_CONTEXT_LEN);
1388 +                       } else if (!sloppy)
1389                                 goto bad_parameter;
1390                         sprintf(cbuf, "%s=%s,", opt, opteq+1);
1391                 } else {
1392 @@ -764,9 +791,11 @@ parse_options(char *old_opts, struct nfs
1393  #endif
1394                         } else {
1395                         bad_option:
1396 -                               printf(_("Unsupported nfs mount option: "
1397 -                                        "%s%s\n"), val ? "" : "no", opt);
1398 -                               goto out_bad;
1399 +                               if (!sloppy) {
1400 +                                       printf(_("Unsupported nfs mount option: "
1401 +                                                "%s%s\n"), val ? "" : "no", opt);
1402 +                                       goto out_bad;
1403 +                               }
1404                         }
1405                         sprintf(cbuf, val ? "%s,":"no%s,", opt);
1406                 }
1407 @@ -815,8 +844,7 @@ nfsmnt_check_compat(const struct pmap *n
1408  
1409  int
1410  nfsmount(const char *spec, const char *node, int *flags,
1411 -        char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1412 -        int running_bg)
1413 +        char **extra_opts, char **mount_opts, int running_bg)
1414  {
1415         static char *prev_bg_host;
1416         char hostdir[1024];
1417 @@ -847,9 +875,7 @@ nfsmount(const char *spec, const char *n
1418  
1419         /* The version to try is either specified or 0
1420            In case it is 0 we tell the caller what we tried */
1421 -       if (!*nfs_mount_vers)
1422 -               *nfs_mount_vers = find_kernel_nfs_mount_version();
1423 -       nfs_mount_version = *nfs_mount_vers;
1424 +       nfs_mount_version = find_kernel_nfs_mount_version();
1425  
1426         retval = EX_FAIL;
1427         fsock = -1;
1428 @@ -1090,12 +1116,14 @@ nfsmount(const char *spec, const char *n
1429  
1430                 flavor = mountres->auth_flavors.auth_flavors_val;
1431                 while (--i >= 0) {
1432 -                       if (flavor[i] == data.pseudoflavor)
1433 -                               yum = 1;
1434  #ifdef NFS_MOUNT_DEBUG
1435 -                       printf("auth flavor %d: %d\n",
1436 -                               i, flavor[i]);
1437 +                       printf("auth flavor[%d] %d\n", i, flavor[i]);
1438  #endif
1439 +                       if (flavor[i] == data.pseudoflavor ||
1440 +                               flavor[i] == AUTH_NONE) {
1441 +                               yum = 1;
1442 +                               break;
1443 +                       }
1444                 }
1445                 if (!yum) {
1446                         fprintf(stderr,
1447 diff -puN support/nfs/conn.c~CITI_NFS4_ALL support/nfs/conn.c
1448 --- nfs-utils-1.0.11/support/nfs/conn.c~CITI_NFS4_ALL   2007-02-26 18:52:15.411170000 -0500
1449 +++ nfs-utils-1.0.11-kwc/support/nfs/conn.c     2007-02-26 18:52:15.506075000 -0500
1450 @@ -98,7 +98,7 @@ int get_socket(struct sockaddr_in *saddr
1451                         return RPC_ANYSOCK;
1452                 }
1453         }
1454 -       if (type == SOCK_STREAM || type == SOCK_DGRAM) {
1455 +       if (type == SOCK_STREAM) {
1456                 cc = connect(so, (struct sockaddr *)saddr, namelen);
1457                 if (cc < 0) {
1458                         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
1459 diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c
1460 --- nfs-utils-1.0.11/utils/gssd/gssd.c~CITI_NFS4_ALL    2007-02-26 18:52:17.909847000 -0500
1461 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd.c      2007-02-26 18:52:21.146491000 -0500
1462 @@ -53,7 +53,8 @@
1463  #include "gss_util.h"
1464  #include "krb5_util.h"
1465  
1466 -char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
1467 +char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
1468 +char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
1469  char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
1470  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
1471  int  use_memcache = 0;
1472 @@ -111,8 +112,8 @@ main(int argc, char *argv[])
1473                                 rpc_verbosity++;
1474                                 break;
1475                         case 'p':
1476 -                               strncpy(pipefsdir, optarg, sizeof(pipefsdir));
1477 -                               if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
1478 +                               strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
1479 +                               if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
1480                                         errx(1, "pipefs path name too long");
1481                                 break;
1482                         case 'k':
1483 @@ -130,10 +131,10 @@ main(int argc, char *argv[])
1484                                 break;
1485                 }
1486         }
1487 -       strncat(pipefsdir + strlen(pipefsdir), "/" GSSD_SERVICE_NAME,
1488 -               sizeof(pipefsdir)-strlen(pipefsdir));
1489 -       if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
1490 -               errx(1, "pipefs path name too long");
1491 +       snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
1492 +                pipefs_dir, GSSD_SERVICE_NAME);
1493 +       if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
1494 +               errx(1, "pipefs_nfsdir path name too long");
1495  
1496         if ((progname = strrchr(argv[0], '/')))
1497                 progname++;
1498 @@ -161,6 +162,8 @@ main(int argc, char *argv[])
1499  
1500         /* Process keytab file and get machine credentials */
1501         gssd_refresh_krb5_machine_creds();
1502 +       /* Determine Kerberos information from the kernel */
1503 +       gssd_obtain_kernel_krb5_info();
1504  
1505         gssd_run();
1506         printerr(0, "gssd_run returned!\n");
1507 diff -puN utils/gssd/gssd.h~CITI_NFS4_ALL utils/gssd/gssd.h
1508 --- nfs-utils-1.0.11/utils/gssd/gssd.h~CITI_NFS4_ALL    2007-02-26 18:52:18.243847000 -0500
1509 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd.h      2007-02-26 18:52:19.072395000 -0500
1510 @@ -58,7 +58,8 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
1511  
1512  
1513  
1514 -extern char                    pipefsdir[PATH_MAX];
1515 +extern char                    pipefs_dir[PATH_MAX];
1516 +extern char                    pipefs_nfsdir[PATH_MAX];
1517  extern char                    keytabfile[PATH_MAX];
1518  extern char                    ccachedir[PATH_MAX];
1519  extern int                     use_memcache;
1520 diff -puN utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL utils/gssd/gssd_main_loop.c
1521 --- nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL  2007-02-26 18:52:18.584642000 -0500
1522 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd_main_loop.c    2007-02-26 18:52:19.111395000 -0500
1523 @@ -106,9 +106,9 @@ gssd_run()
1524         dn_act.sa_flags = SA_SIGINFO;
1525         sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
1526  
1527 -       if ((fd = open(pipefsdir, O_RDONLY)) == -1) {
1528 +       if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
1529                 printerr(0, "ERROR: failed to open %s: %s\n",
1530 -                        pipefsdir, strerror(errno));
1531 +                        pipefs_nfsdir, strerror(errno));
1532                 exit(1);
1533         }
1534         fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
1535 diff -puN utils/gssd/gssd_proc.c~CITI_NFS4_ALL utils/gssd/gssd_proc.c
1536 --- nfs-utils-1.0.11/utils/gssd/gssd_proc.c~CITI_NFS4_ALL       2007-02-26 18:52:18.936395000 -0500
1537 +++ nfs-utils-1.0.11-kwc/utils/gssd/gssd_proc.c 2007-02-26 18:52:19.165395000 -0500
1538 @@ -80,19 +80,19 @@
1539   *     with an index into pollarray[], and other basic data about that client.
1540   *
1541   * Directory structure: created by the kernel nfs client
1542 - *      /pipefsdir/clntXX             : one per rpc_clnt struct in the kernel
1543 - *      /pipefsdir/clntXX/krb5        : read uid for which kernel wants
1544 - *                                      a context, write the resulting context
1545 - *      /pipefsdir/clntXX/info        : stores info such as server name
1546 + *      {pipefs_nfsdir}/clntXX             : one per rpc_clnt struct in the kernel
1547 + *      {pipefs_nfsdir}/clntXX/krb5        : read uid for which kernel wants
1548 + *                                         a context, write the resulting context
1549 + *      {pipefs_nfsdir}/clntXX/info        : stores info such as server name
1550   *
1551   * Algorithm:
1552 - *      Poll all /pipefsdir/clntXX/krb5 files.  When ready, data read
1553 + *      Poll all {pipefs_nfsdir}/clntXX/krb5 files.  When ready, data read
1554   *      is a uid; performs rpcsec_gss context initialization protocol to
1555   *      get a cred for that user.  Writes result to corresponding krb5 file
1556   *      in a form the kernel code will understand.
1557   *      In addition, we make sure we are notified whenever anything is
1558 - *      created or destroyed in pipefsdir/ or in an of the clntXX directories,
1559 - *      and rescan the whole pipefsdir when this happens.
1560 + *      created or destroyed in {pipefs_nfsdir} or in an of the clntXX directories,
1561 + *      and rescan the whole {pipefs_nfsdir} when this happens.
1562   */
1563  
1564  struct pollfd * pollarray;
1565 @@ -389,16 +389,16 @@ update_client_list(void)
1566         struct dirent **namelist;
1567         int i, j;
1568  
1569 -       if (chdir(pipefsdir) < 0) {
1570 +       if (chdir(pipefs_nfsdir) < 0) {
1571                 printerr(0, "ERROR: can't chdir to %s: %s\n",
1572 -                        pipefsdir, strerror(errno));
1573 +                        pipefs_nfsdir, strerror(errno));
1574                 return -1;
1575         }
1576  
1577 -       j = scandir(pipefsdir, &namelist, NULL, alphasort);
1578 +       j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
1579         if (j < 0) {
1580                 printerr(0, "ERROR: can't scandir %s: %s\n",
1581 -                        pipefsdir, strerror(errno));
1582 +                        pipefs_nfsdir, strerror(errno));
1583                 return -1;
1584         }
1585         update_old_clients(namelist, j);
1586 diff -puN support/include/nfslib.h~CITI_NFS4_ALL support/include/nfslib.h
1587 --- nfs-utils-1.0.11/support/include/nfslib.h~CITI_NFS4_ALL     2007-02-26 18:52:19.914943000 -0500
1588 +++ nfs-utils-1.0.11-kwc/support/include/nfslib.h       2007-02-26 18:52:20.001943000 -0500
1589 @@ -57,6 +57,9 @@ enum cle_maptypes {
1590         CLE_MAP_UGIDD,
1591  };
1592  
1593 +#define SECFLAVOR_COUNT 7
1594 +extern char *secflavor_name[SECFLAVOR_COUNT];
1595 +
1596  /*
1597   * Data related to a single exports entry as returned by getexportent.
1598   * FIXME: export options should probably be parsed at a later time to
1599 @@ -83,6 +86,8 @@ struct exportent {
1600         int             e_fslocmethod;
1601         char *          e_fslocdata;
1602         char *          e_uuid;
1603 +       int             e_secinfo_order[SECFLAVOR_COUNT+1];
1604 +       int             e_secinfo_flags[SECFLAVOR_COUNT];
1605  };
1606  
1607  struct rmtabent {
1608 @@ -96,6 +101,7 @@ struct rmtabent {
1609   */
1610  void                   setexportent(char *fname, char *type);
1611  struct exportent *     getexportent(int,int);
1612 +void                   secinfo_show(FILE *fp, struct exportent *ep);
1613  void                   putexportent(struct exportent *xep);
1614  void                   endexportent(void);
1615  struct exportent *     mkexportent(char *hname, char *path, char *opts);
1616 diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c
1617 --- nfs-utils-1.0.11/utils/gssd/krb5_util.c~CITI_NFS4_ALL       2007-02-26 18:52:20.789535000 -0500
1618 +++ nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.c 2007-02-26 18:52:21.202491000 -0500
1619 @@ -97,6 +97,7 @@
1620  #include "config.h"
1621  #include <sys/param.h>
1622  #include <rpc/rpc.h>
1623 +#include <sys/types.h>
1624  #include <sys/stat.h>
1625  #include <sys/socket.h>
1626  #include <arpa/inet.h>
1627 @@ -105,6 +106,7 @@
1628  #include <stdlib.h>
1629  #include <string.h>
1630  #include <dirent.h>
1631 +#include <fcntl.h>
1632  #include <errno.h>
1633  #include <time.h>
1634  #include <gssapi/gssapi.h>
1635 @@ -123,6 +125,10 @@
1636  /* Global list of principals/cache file names for machine credentials */
1637  struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
1638  
1639 +/* Encryption types supported by the kernel rpcsec_gss code */
1640 +int num_krb5_enctypes = 0;
1641 +krb5_enctype *krb5_enctypes = NULL;
1642 +
1643  /*==========================*/
1644  /*===  Internal routines ===*/
1645  /*==========================*/
1646 @@ -256,56 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
1647  }
1648  
1649  
1650 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1651 -/*
1652 - * this routine obtains a credentials handle via gss_acquire_cred()
1653 - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
1654 - * types negotiated.
1655 - *
1656 - * XXX Should call some function to determine the enctypes supported
1657 - * by the kernel. (Only need to do that once!)
1658 - *
1659 - * Returns:
1660 - *     0 => all went well
1661 - *     -1 => there was an error
1662 - */
1663 -
1664 -int
1665 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
1666 -{
1667 -       u_int maj_stat, min_stat;
1668 -       gss_cred_id_t credh;
1669 -       gss_OID_set_desc  desired_mechs;
1670 -       krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
1671 -       int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
1672 -
1673 -       /* We only care about getting a krb5 cred */
1674 -       desired_mechs.count = 1;
1675 -       desired_mechs.elements = &krb5oid;
1676 -
1677 -       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
1678 -                                   &desired_mechs, GSS_C_INITIATE,
1679 -                                   &credh, NULL, NULL);
1680 -
1681 -       if (maj_stat != GSS_S_COMPLETE) {
1682 -               pgsserr("gss_acquire_cred",
1683 -                       maj_stat, min_stat, &krb5oid);
1684 -               return -1;
1685 -       }
1686 -
1687 -       maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
1688 -                                            num_enctypes, &enctypes);
1689 -       if (maj_stat != GSS_S_COMPLETE) {
1690 -               pgsserr("gss_set_allowable_enctypes",
1691 -                       maj_stat, min_stat, &krb5oid);
1692 -               return -1;
1693 -       }
1694 -       sec->cred = credh;
1695 -
1696 -       return 0;
1697 -}
1698 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
1699 -
1700  /*
1701   * Obtain credentials via a key in the keytab given
1702   * a keytab handle and a gssd_k5_kt_princ structure.
1703 @@ -609,6 +565,56 @@ gssd_set_krb5_ccache_name(char *ccname)
1704  #endif
1705  }
1706  
1707 +/*
1708 + * Parse the supported encryption type information
1709 + */
1710 +static int
1711 +parse_enctypes(char *enctypes)
1712 +{
1713 +       int n = 0;
1714 +       char *curr, *comma;
1715 +       int i;
1716 +
1717 +       /* Just in case this ever gets called more than once */
1718 +       if (krb5_enctypes != NULL) {
1719 +               free(krb5_enctypes);
1720 +               krb5_enctypes = NULL;
1721 +               num_krb5_enctypes = 0;
1722 +       }
1723 +
1724 +       /* count the number of commas */
1725 +       for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
1726 +               comma = strchr(curr, ',');
1727 +               if (comma != NULL)
1728 +                       n++;
1729 +               else
1730 +                       break;
1731 +       }
1732 +       /* If no more commas and we're not at the end, there's one more value */
1733 +       if (*curr != '\0')
1734 +               n++;
1735 +
1736 +       /* Empty string, return an error */
1737 +       if (n == 0)
1738 +               return ENOENT;
1739 +
1740 +       /* Allocate space for enctypes array */
1741 +       if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
1742 +               return ENOMEM;
1743 +       }
1744 +
1745 +       /* Now parse each value into the array */
1746 +       for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
1747 +               krb5_enctypes[i++] = atoi(curr);
1748 +               comma = strchr(curr, ',');
1749 +               if (comma == NULL)
1750 +                       break;
1751 +       }
1752 +
1753 +       num_krb5_enctypes = n;
1754 +       return 0;
1755 +}
1756 +
1757  /*==========================*/
1758  /*===  External routines ===*/
1759  /*==========================*/
1760 @@ -860,3 +866,125 @@ gssd_destroy_krb5_machine_creds(void)
1761         krb5_free_context(context);
1762  }
1763  
1764 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1765 +/*
1766 + * this routine obtains a credentials handle via gss_acquire_cred()
1767 + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
1768 + * types negotiated.
1769 + *
1770 + * Returns:
1771 + *     0 => all went well
1772 + *     -1 => there was an error
1773 + */
1774 +
1775 +int
1776 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
1777 +{
1778 +       u_int maj_stat, min_stat;
1779 +       gss_cred_id_t credh;
1780 +       gss_OID_set_desc  desired_mechs;
1781 +       krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
1782 +       int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
1783 +
1784 +       /* We only care about getting a krb5 cred */
1785 +       desired_mechs.count = 1;
1786 +       desired_mechs.elements = &krb5oid;
1787 +
1788 +       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
1789 +                                   &desired_mechs, GSS_C_INITIATE,
1790 +                                   &credh, NULL, NULL);
1791 +
1792 +       if (maj_stat != GSS_S_COMPLETE) {
1793 +               pgsserr("gss_acquire_cred",
1794 +                       maj_stat, min_stat, &krb5oid);
1795 +               return -1;
1796 +       }
1797 +
1798 +       /*
1799 +        * If we failed for any reason to produce global
1800 +        * list of supported enctypes, use local default here.
1801 +        */
1802 +       if (krb5_enctypes == NULL)
1803 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
1804 +                                       &krb5oid, num_enctypes, &enctypes);
1805 +       else
1806 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
1807 +                                       &krb5oid, num_krb5_enctypes,
1808 +                                       krb5_enctypes);
1809 +       if (maj_stat != GSS_S_COMPLETE) {
1810 +               pgsserr("gss_set_allowable_enctypes",
1811 +                       maj_stat, min_stat, &krb5oid);
1812 +               return -1;
1813 +       }
1814 +       sec->cred = credh;
1815 +
1816 +       return 0;
1817 +}
1818 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
1819 +
1820 +/*
1821 + * Obtain supported enctypes from kernel.
1822 + * Set defaults if info is not available.
1823 + */
1824 +void
1825 +gssd_obtain_kernel_krb5_info(void)
1826 +{
1827 +       char enctype_file_name[128];
1828 +       char buf[1024];
1829 +       char enctypes[128];
1830 +       int nscanned;
1831 +       int fd;
1832 +       int use_default_enctypes = 0;
1833 +       int nbytes, numfields;
1834 +       char default_enctypes[] = "1,3,2";
1835 +       int code;
1836 +
1837 +       snprintf(enctype_file_name, sizeof(enctype_file_name),
1838 +                "%s/%s", pipefs_dir, "krb5_info");
1839 +
1840 +       if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
1841 +               printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
1842 +                        "Unable to open '%s'. Unable to determine "
1843 +                        "Kerberos encryption types supported by the "
1844 +                        "kernel; using defaults (%s).\n",
1845 +                        enctype_file_name, default_enctypes);
1846 +               use_default_enctypes = 1;
1847 +               goto do_the_parse;
1848 +       }
1849 +       memset(buf, 0, sizeof(buf));
1850 +       if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) {
1851 +               printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
1852 +                        "Error reading Kerberos encryption type "
1853 +                        "information file '%s'; using defaults (%s).\n",
1854 +                        enctype_file_name, default_enctypes);
1855 +               use_default_enctypes = 1;
1856 +               close(fd);
1857 +               goto do_the_parse;
1858 +       }
1859 +       close(fd);
1860 +       numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned);
1861 +       if (numfields < 1) {
1862 +               printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
1863 +                        "error parsing Kerberos encryption type "
1864 +                        "information from file '%s'; using defaults (%s).\n",
1865 +                        enctype_file_name, default_enctypes);
1866 +               use_default_enctypes = 1;
1867 +               goto do_the_parse;
1868 +       }
1869 +       if (nbytes > nscanned) {
1870 +               printerr(2, "gssd_obtain_kernel_krb5_info: "
1871 +                        "Ignoring extra information, '%s', from '%s'\n",
1872 +                        buf+nscanned, enctype_file_name);
1873 +               goto do_the_parse;
1874 +       }
1875 +  do_the_parse:
1876 +       if (use_default_enctypes)
1877 +               strcpy(enctypes, default_enctypes);
1878 +
1879 +       if ((code = parse_enctypes(enctypes)) != 0) {
1880 +               printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
1881 +                        "parse_enctypes%s failed with code %d\n",
1882 +                        use_default_enctypes ? " (with default enctypes)" : "",
1883 +                        code);
1884 +       }
1885 +}
1886 diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h
1887 --- nfs-utils-1.0.11/utils/gssd/krb5_util.h~CITI_NFS4_ALL       2007-02-26 18:52:21.065491000 -0500
1888 +++ nfs-utils-1.0.11-kwc/utils/gssd/krb5_util.h 2007-02-26 18:52:21.305491000 -0500
1889 @@ -22,6 +22,8 @@ int  gssd_refresh_krb5_machine_creds(voi
1890  void gssd_free_krb5_machine_cred_list(char **list);
1891  void gssd_setup_krb5_machine_gss_ccache(char *servername);
1892  void gssd_destroy_krb5_machine_creds(void);
1893 +void gssd_obtain_kernel_krb5_info(void);
1894 +
1895  
1896  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
1897  int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
1898 diff -puN utils/gssd/context.h~CITI_NFS4_ALL utils/gssd/context.h
1899 --- nfs-utils-1.0.11/utils/gssd/context.h~CITI_NFS4_ALL 2007-02-26 18:52:21.831041000 -0500
1900 +++ nfs-utils-1.0.11-kwc/utils/gssd/context.h   2007-02-26 18:52:22.471949000 -0500
1901 @@ -1,5 +1,5 @@
1902  /*
1903 -  Copyright (c) 2004 The Regents of the University of Michigan.
1904 +  Copyright (c) 2004-2006 The Regents of the University of Michigan.
1905    All rights reserved.
1906  
1907    Redistribution and use in source and binary forms, with or without
1908 @@ -36,6 +36,10 @@
1909  /* Hopefully big enough to hold any serialized context */
1910  #define MAX_CTX_LEN 4096
1911  
1912 +/* New context format flag values */
1913 +#define KRB5_CTX_FLAG_INITIATOR         0x00000001
1914 +#define KRB5_CTX_FLAG_CFX               0x00000002
1915 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
1916  
1917  int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
1918                                  gss_OID mech);
1919 diff -puN utils/gssd/context_lucid.c~CITI_NFS4_ALL utils/gssd/context_lucid.c
1920 --- nfs-utils-1.0.11/utils/gssd/context_lucid.c~CITI_NFS4_ALL   2007-02-26 18:52:22.123039000 -0500
1921 +++ nfs-utils-1.0.11-kwc/utils/gssd/context_lucid.c     2007-02-26 18:52:22.513907000 -0500
1922 @@ -40,6 +40,7 @@
1923  #include <stdio.h>
1924  #include <syslog.h>
1925  #include <string.h>
1926 +#include <errno.h>
1927  #include "gss_util.h"
1928  #include "gss_oids.h"
1929  #include "err_util.h"
1930 @@ -113,15 +114,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc
1931          * Note that the rfc1964 version only supports DES enctypes.
1932          */
1933         if (lctx->rfc1964_kd.ctx_key.type != 4) {
1934 -               printerr(1, "prepare_krb5_rfc1964_buffer: "
1935 -                           "overriding heimdal keytype (%d => %d)\n",
1936 -                           lctx->rfc1964_kd.ctx_key.type, 4);
1937 +               printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
1938 +                        __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
1939                 lctx->rfc1964_kd.ctx_key.type = 4;
1940         }
1941  #endif
1942 -       printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
1943 -                "enctype %d and length %d\n",
1944 -                lctx->rfc1964_kd.ctx_key.type,
1945 +       printerr(2, "%s: serializing keys with enctype %d and length %d\n",
1946 +                __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
1947                  lctx->rfc1964_kd.ctx_key.length);
1948  
1949         /* derive the encryption key and copy it into buffer */
1950 @@ -152,15 +151,361 @@ out_err:
1951         return -1;
1952  }
1953  
1954 -static int
1955 -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
1956 -       gss_buffer_desc *buf)
1957 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1958 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1959 +
1960 +/* for 3DES */
1961 +#define KG_USAGE_SEAL 22
1962 +#define KG_USAGE_SIGN 23
1963 +#define KG_USAGE_SEQ  24
1964 +
1965 +/* for rfc???? */
1966 +#define KG_USAGE_ACCEPTOR_SEAL  22
1967 +#define KG_USAGE_ACCEPTOR_SIGN  23
1968 +#define KG_USAGE_INITIATOR_SEAL 24
1969 +#define KG_USAGE_INITIATOR_SIGN 25
1970 +
1971 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
1972 +enum seal_alg {
1973 +  SEAL_ALG_NONE            = 0xffff,
1974 +  SEAL_ALG_DES             = 0x0000,
1975 +  SEAL_ALG_1               = 0x0001, /* not published */
1976 +  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
1977 +  SEAL_ALG_DES3KD          = 0x0002
1978 +};
1979 +
1980 +#define KEY_USAGE_SEED_ENCRYPTION      0xAA
1981 +#define KEY_USAGE_SEED_INTEGRITY       0x55
1982 +#define KEY_USAGE_SEED_CHECKSUM                0x99
1983 +#define K5CLENGTH 5
1984 +
1985 +/* Flags for version 2 context flags */
1986 +#define KRB5_CTX_FLAG_INITIATOR                0x00000001
1987 +#define KRB5_CTX_FLAG_CFX              0x00000002
1988 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
1989 +
1990 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1991 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
1992 +/*
1993 + * We don't have "legal" access to these MIT-only
1994 + * structures located in libk5crypto
1995 + */
1996 +extern void krb5int_enc_arcfour;
1997 +extern void krb5int_enc_des3;
1998 +extern void krb5int_enc_aes128;
1999 +extern void krb5int_enc_aes256;
2000 +extern int krb5_derive_key();
2001 +
2002 +static void
2003 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
2004  {
2005 -       printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
2006 -       return -1;
2007 +       memset(kout, '\0', sizeof(kout));
2008 +#ifdef HAVE_KRB5
2009 +       kout->enctype = lin->type;
2010 +       kout->length = lin->length;
2011 +       kout->contents = lin->data;
2012 +#else
2013 +       kout->keytype = lin->type;
2014 +       kout->keyvalue.length = lin->length;
2015 +       kout->keyvalue.data = lin->data;
2016 +#endif
2017  }
2018  
2019 +static void
2020 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
2021 +{
2022 +       memset(lout, '\0', sizeof(lout));
2023 +#ifdef HAVE_KRB5
2024 +       lout->type = kin->enctype;
2025 +       lout->length = kin->length;
2026 +       lout->data = kin->contents;
2027 +#else
2028 +       lout->type = kin->keytype;
2029 +       lout->length = kin->keyvalue.length;
2030 +       memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
2031 +#endif
2032 +}
2033  
2034 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2035 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2036 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2037 +/* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
2038 +/*
2039 + * Function to derive a new key from a given key and given constant data.
2040 + */
2041 +static krb5_error_code
2042 +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
2043 +                int usage, char extra)
2044 +{
2045 +       krb5_error_code code;
2046 +       unsigned char constant_data[K5CLENGTH];
2047 +       krb5_data datain;
2048 +       int keylength;
2049 +       void *enc;
2050 +       krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
2051 +#ifdef HAVE_HEIMDAL
2052 +       krb5_context kcontext;
2053 +       krb5_keyblock *outkey;
2054 +#endif
2055 +
2056 +       /*
2057 +        * XXX Hack alert.  We don't have "legal" access to these
2058 +        * values and structures located in libk5crypto
2059 +        */
2060 +       switch (in->type) {
2061 +       case ENCTYPE_DES3_CBC_SHA1:
2062 +#ifdef HAVE_KRB5
2063 +       case ENCTYPE_DES3_CBC_RAW:
2064 +#endif
2065 +               keylength = 24;
2066 +#ifdef HAVE_KRB5
2067 +               enc = &krb5int_enc_des3;
2068 +#endif
2069 +               break;
2070 +       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
2071 +               keylength = 16;
2072 +#ifdef HAVE_KRB5
2073 +               enc = &krb5int_enc_aes128;
2074 +#endif
2075 +               break;
2076 +       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
2077 +               keylength = 32;
2078 +#ifdef HAVE_KRB5
2079 +               enc = &krb5int_enc_aes256;
2080 +#endif
2081 +               break;
2082 +       default:
2083 +               code = KRB5_BAD_ENCTYPE;
2084 +               goto out;
2085 +       }
2086 +
2087 +       /* allocate memory for output key */
2088 +       if ((out->data = malloc(keylength)) == NULL) {
2089 +               code = ENOMEM;
2090 +               goto out;
2091 +       }
2092 +       out->length = keylength;
2093 +       out->type = in->type;
2094 +
2095 +       /* Convert to correct format for call to krb5_derive_key */
2096 +       key_lucid_to_krb5(in, &kin);
2097 +       key_lucid_to_krb5(out, &kout);
2098 +
2099 +       datain.data = (char *) constant_data;
2100 +       datain.length = K5CLENGTH;
2101 +
2102 +       ((char *)(datain.data))[0] = (usage>>24)&0xff;
2103 +       ((char *)(datain.data))[1] = (usage>>16)&0xff;
2104 +       ((char *)(datain.data))[2] = (usage>>8)&0xff;
2105 +       ((char *)(datain.data))[3] = usage&0xff;
2106 +
2107 +       ((char *)(datain.data))[4] = (char) extra;
2108 +
2109 +#ifdef HAVE_KRB5
2110 +       code = krb5_derive_key(enc, &kin, &kout, &datain);
2111 +#else
2112 +       if ((code = krb5_init_context(&kcontext))) {
2113 +       }
2114 +       code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
2115 +#endif
2116 +       if (code) {
2117 +               free(out->data);
2118 +               out->data = NULL;
2119 +               goto out;
2120 +       }
2121 +#ifdef HAVE_KRB5
2122 +       key_krb5_to_lucid(&kout, out);
2123 +#else
2124 +       key_krb5_to_lucid(outkey, out);
2125 +       krb5_free_keyblock(kcontext, outkey);
2126 +       krb5_free_context(kcontext);
2127 +#endif
2128 +
2129 +  out:
2130 +       if (code)
2131 +               printerr(0, "ERROR: %s: returning error %d (%s)\n",
2132 +                        __FUNCTION__, code, error_message(code));
2133 +       return (code);
2134 +}
2135 +
2136 +
2137 +/*
2138 + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
2139 + * to send to the kernel for newer encryption types -- or for DES3.
2140 + *
2141 + * The new format is:
2142 + *
2143 + *     u32 initiate;                   ( whether we are the initiator or not )
2144 + *     s32 endtime;
2145 + *     u32 flags;
2146 + *     #define KRB5_CTX_FLAG_INITIATOR         0x00000001
2147 + *     #define KRB5_CTX_FLAG_CFX               0x00000002
2148 + *     #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
2149 + *     u64 seq_send;
2150 + *     u32  enctype;                   ( encrption type of keys )
2151 + *     u32  size_of_each_key;          ( size of each key in bytes )
2152 + *     u32  number_of_keys;            ( N -- should always be 3 for now )
2153 + *     keydata-1;                      ( Ke )
2154 + *     keydata-2;                      ( Ki )
2155 + *     keydata-3;                      ( Kc )
2156 + *
2157 + */
2158 +static int
2159 +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
2160 +                           gss_buffer_desc *buf)
2161 +{
2162 +       char *p, *end;
2163 +       uint32_t v2_flags = 0;
2164 +       gss_krb5_lucid_key_t enc_key;
2165 +       gss_krb5_lucid_key_t derived_key;
2166 +       gss_buffer_desc fakeoid;
2167 +       uint32_t enctype;
2168 +       uint32_t keysize;
2169 +       uint32_t numkeys;
2170 +
2171 +       memset(&enc_key, 0, sizeof(enc_key));
2172 +       memset(&fakeoid, 0, sizeof(fakeoid));
2173 +
2174 +       if (!(buf->value = calloc(1, MAX_CTX_LEN)))
2175 +               goto out_err;
2176 +       p = buf->value;
2177 +       end = buf->value + MAX_CTX_LEN;
2178 +
2179 +       /* Version 2 */
2180 +       if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
2181 +       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
2182 +
2183 +       if (lctx->initiate)
2184 +               v2_flags |= KRB5_CTX_FLAG_INITIATOR;
2185 +       if (lctx->protocol != 0)
2186 +               v2_flags |= KRB5_CTX_FLAG_CFX;
2187 +       if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
2188 +               v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
2189 +
2190 +       if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
2191 +
2192 +       if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
2193 +
2194 +       /* Protocol 0 here implies DES3 or RC4 */
2195 +       printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
2196 +       if (lctx->protocol == 0) {
2197 +               enctype = lctx->rfc1964_kd.ctx_key.type;
2198 +#ifdef HAVE_HEIMDAL
2199 +               /*
2200 +                * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for
2201 +                * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16).
2202 +                * Force the Heimdal enctype to 6.
2203 +                */
2204 +               if (enctype == ENCTYPE_DES3_CBC_SHA1) {
2205 +                       printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
2206 +                                __FUNCTION__, enctype, 6);
2207 +
2208 +                       enctype = 6;
2209 +               }
2210 +#endif
2211 +               keysize = lctx->rfc1964_kd.ctx_key.length;
2212 +               numkeys = 3;    /* XXX is always gonna be three? */
2213 +       } else {
2214 +               if (lctx->cfx_kd.have_acceptor_subkey) {
2215 +                       enctype = lctx->cfx_kd.acceptor_subkey.type;
2216 +                       keysize = lctx->cfx_kd.acceptor_subkey.length;
2217 +               } else {
2218 +                       enctype = lctx->cfx_kd.ctx_key.type;
2219 +                       keysize = lctx->cfx_kd.ctx_key.length;
2220 +               }
2221 +               numkeys = 3;
2222 +       }
2223 +       printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
2224 +                __FUNCTION__, numkeys, enctype, keysize);
2225 +       if (WRITE_BYTES(&p, end, enctype)) goto out_err;
2226 +       if (WRITE_BYTES(&p, end, keysize)) goto out_err;
2227 +       if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
2228 +
2229 +       if (lctx->protocol == 0) {
2230 +               /* derive and send down: Ke, Ki, and Kc */
2231 +               /* Ke */
2232 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
2233 +                               lctx->rfc1964_kd.ctx_key.length))
2234 +                       goto out_err;
2235 +
2236 +               /* Ki */
2237 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
2238 +                               lctx->rfc1964_kd.ctx_key.length))
2239 +                       goto out_err;
2240 +
2241 +               /* Kc */
2242 +               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
2243 +                               &derived_key,
2244 +                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
2245 +                       goto out_err;
2246 +               if (write_bytes(&p, end, derived_key.data,
2247 +                               derived_key.length))
2248 +                       goto out_err;
2249 +               free(derived_key.data);
2250 +       } else {
2251 +               gss_krb5_lucid_key_t *keyptr;
2252 +               uint32_t sign_usage, seal_usage;
2253 +
2254 +               if (lctx->cfx_kd.have_acceptor_subkey)
2255 +                       keyptr = &lctx->cfx_kd.acceptor_subkey;
2256 +               else
2257 +                       keyptr = &lctx->cfx_kd.ctx_key;
2258 +
2259 +               if (lctx->initiate == 1) {
2260 +                       sign_usage = KG_USAGE_INITIATOR_SIGN;
2261 +                       seal_usage = KG_USAGE_INITIATOR_SEAL;
2262 +               } else {
2263 +                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
2264 +                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
2265 +               }
2266 +
2267 +               /* derive and send down: Ke, Ki, and Kc */
2268 +
2269 +               /* Ke */
2270 +               if (derive_key_lucid(keyptr, &derived_key,
2271 +                              seal_usage, KEY_USAGE_SEED_ENCRYPTION))
2272 +                       goto out_err;
2273 +               if (write_bytes(&p, end, derived_key.data,
2274 +                               derived_key.length))
2275 +                       goto out_err;
2276 +               free(derived_key.data);
2277 +
2278 +               /* Ki */
2279 +               if (derive_key_lucid(keyptr, &derived_key,
2280 +                              seal_usage, KEY_USAGE_SEED_INTEGRITY))
2281 +                       goto out_err;
2282 +               if (write_bytes(&p, end, derived_key.data,
2283 +                               derived_key.length))
2284 +                       goto out_err;
2285 +               free(derived_key.data);
2286 +
2287 +               /* Kc */
2288 +               if (derive_key_lucid(keyptr, &derived_key,
2289 +                              sign_usage, KEY_USAGE_SEED_CHECKSUM))
2290 +                       goto out_err;
2291 +               if (write_bytes(&p, end, derived_key.data,
2292 +                               derived_key.length))
2293 +                       goto out_err;
2294 +               free(derived_key.data);
2295 +       }
2296 +
2297 +       buf->length = p - (char *)buf->value;
2298 +       return 0;
2299 +
2300 +out_err:
2301 +       printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
2302 +                __FUNCTION__);
2303 +       if (buf->value) {
2304 +               free(buf->value);
2305 +               buf->value = NULL;
2306 +       }
2307 +       buf->length = 0;
2308 +       if (enc_key.data) {
2309 +               free(enc_key.data);
2310 +               enc_key.data = NULL;
2311 +       }
2312 +       return -1;
2313 +}
2314  int
2315  serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
2316  {
2317 @@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2318         gss_krb5_lucid_context_v1_t *lctx = 0;
2319         int retcode = 0;
2320  
2321 -       printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
2322 +       printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
2323         maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
2324                                                 1, &return_ctx);
2325         if (maj_stat != GSS_S_COMPLETE) {
2326 @@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2327                 break;
2328         }
2329  
2330 -       /* Now lctx points to a lucid context that we can send down to kernel */
2331 -       if (lctx->protocol == 0)
2332 +        /*
2333 +        * Now lctx points to a lucid context that we can send down to kernel
2334 +        *
2335 +        * Note: we send down different information to the kernel depending
2336 +        * on the protocol version and the enctyption type.
2337 +        * For protocol version 0 with all enctypes besides DES3, we use
2338 +        * the original format.  For protocol version != 0 or DES3, we
2339 +        * send down the new style information.
2340 +        */
2341 +
2342 +       if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
2343                 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
2344         else
2345 -               retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
2346 +               retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
2347  
2348         maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
2349         if (maj_stat != GSS_S_COMPLETE) {
2350 @@ -206,8 +560,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2351         }
2352  
2353         if (retcode) {
2354 -               printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
2355 -                        "failed (retcode = %d)\n", retcode);
2356 +               printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
2357 +                        __FUNCTION__, retcode);
2358                 goto out_err;
2359         }
2360  
2361 @@ -217,4 +571,7 @@ out_err:
2362         printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
2363         return -1;
2364  }
2365 +
2366 +
2367 +
2368  #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
2369 diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c
2370 --- nfs-utils-1.0.11/utils/gssd/context_mit.c~CITI_NFS4_ALL     2007-02-26 18:52:22.399022000 -0500
2371 +++ nfs-utils-1.0.11-kwc/utils/gssd/context_mit.c       2007-02-26 18:52:22.561859000 -0500
2372 @@ -1,5 +1,5 @@
2373  /*
2374 -  Copyright (c) 2004 The Regents of the University of Michigan.
2375 +  Copyright (c) 2004-2006 The Regents of the University of Michigan.
2376    All rights reserved.
2377  
2378    Redistribution and use in source and binary forms, with or without
2379 @@ -36,6 +36,7 @@
2380  #include <stdio.h>
2381  #include <syslog.h>
2382  #include <string.h>
2383 +#include <errno.h>
2384  #include <gssapi.h>
2385  #include <rpc/rpc.h>
2386  #include <rpc/auth_gss.h>
2387 @@ -50,8 +51,7 @@
2388  /* XXX argggg, there's gotta be a better way than just duplicating this
2389   * whole struct.  Unfortunately, this is in a "private" header file,
2390   * so this is our best choice at this point :-/
2391 - *
2392 - * XXX Does this match the Heimdal definition?  */
2393 + */
2394  
2395  typedef struct _krb5_gss_ctx_id_rec {
2396     unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
2397 @@ -139,6 +139,124 @@ write_keyblock(char **p, char *end, stru
2398  }
2399  
2400  /*
2401 + * XXX Hack alert! XXX Do NOT submit upstream!
2402 + * XXX Hack alert! XXX Do NOT submit upstream!
2403 + *
2404 + * We shouldn't be using these definitions
2405 + *
2406 + * XXX Hack alert! XXX Do NOT submit upstream!
2407 + * XXX Hack alert! XXX Do NOT submit upstream!
2408 + */
2409 +/* for 3DES */
2410 +#define KG_USAGE_SEAL 22
2411 +#define KG_USAGE_SIGN 23
2412 +#define KG_USAGE_SEQ  24
2413 +
2414 +/* for rfc???? */
2415 +#define KG_USAGE_ACCEPTOR_SEAL  22
2416 +#define KG_USAGE_ACCEPTOR_SIGN  23
2417 +#define KG_USAGE_INITIATOR_SEAL 24
2418 +#define KG_USAGE_INITIATOR_SIGN 25
2419 +
2420 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
2421 +enum seal_alg {
2422 +  SEAL_ALG_NONE            = 0xffff,
2423 +  SEAL_ALG_DES             = 0x0000,
2424 +  SEAL_ALG_1               = 0x0001, /* not published */
2425 +  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
2426 +  SEAL_ALG_DES3KD          = 0x0002
2427 +};
2428 +
2429 +#define KEY_USAGE_SEED_ENCRYPTION      0xAA
2430 +#define KEY_USAGE_SEED_INTEGRITY       0x55
2431 +#define KEY_USAGE_SEED_CHECKSUM                0x99
2432 +#define K5CLENGTH 5
2433 +
2434 +extern void krb5_enc_des3;
2435 +extern void krb5int_enc_des3;
2436 +extern void krb5int_enc_arcfour;
2437 +extern void krb5int_enc_aes128;
2438 +extern void krb5int_enc_aes256;
2439 +extern int krb5_derive_key();
2440 +
2441 +/*
2442 + * XXX Hack alert! XXX Do NOT submit upstream!
2443 + * XXX Hack alert! XXX Do NOT submit upstream!
2444 + *
2445 + * We should be passing down a single key to the kernel
2446 + * and it should be deriving the other keys.  We cannot
2447 + * depend on any of this stuff being accessible in the
2448 + * future.
2449 + *
2450 + * XXX Hack alert! XXX Do NOT submit upstream!
2451 + * XXX Hack alert! XXX Do NOT submit upstream!
2452 + */
2453 +/*
2454 + * Function to derive a new key from a given key and given constant data.
2455 + */
2456 +static krb5_error_code
2457 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
2458 +{
2459 +       krb5_error_code code;
2460 +       unsigned char constant_data[K5CLENGTH];
2461 +       krb5_data datain;
2462 +       int keylength;
2463 +       void *enc;
2464 +
2465 +       switch (in->enctype) {
2466 +#ifdef ENCTYPE_DES3_CBC_RAW
2467 +       case ENCTYPE_DES3_CBC_RAW:
2468 +               keylength = 24;
2469 +/* Extra hack, the structure was renamed as rc4 was added... */
2470 +#if defined(ENCTYPE_ARCFOUR_HMAC)
2471 +               enc = &krb5int_enc_des3;
2472 +#else
2473 +               enc = &krb5_enc_des3;
2474 +#endif
2475 +               break;
2476 +#endif
2477 +#ifdef ENCTYPE_ARCFOUR_HMAC
2478 +       case ENCTYPE_ARCFOUR_HMAC:
2479 +               keylength = 16;
2480 +               enc = &krb5int_enc_arcfour;
2481 +               break;
2482 +#endif
2483 +       default:
2484 +               code = KRB5_BAD_ENCTYPE;
2485 +               goto out;
2486 +       }
2487 +
2488 +       /* allocate memory for output key */
2489 +       if ((out->contents = malloc(keylength)) == NULL) {
2490 +               code = ENOMEM;
2491 +               goto out;
2492 +       }
2493 +       out->length = keylength;
2494 +       out->enctype = in->enctype;
2495 +
2496 +       datain.data = (char *) constant_data;
2497 +       datain.length = K5CLENGTH;
2498 +
2499 +       datain.data[0] = (usage>>24)&0xff;
2500 +       datain.data[1] = (usage>>16)&0xff;
2501 +       datain.data[2] = (usage>>8)&0xff;
2502 +       datain.data[3] = usage&0xff;
2503 +
2504 +       datain.data[4] = (char) extra;
2505 +
2506 +       if ((code = krb5_derive_key(enc, in, out, &datain))) {
2507 +               free(out->contents);
2508 +               out->contents = NULL;
2509 +       }
2510 +
2511 +  out:
2512 +       if (code)
2513 +               printerr(0, "ERROR: derive_key returning error %d (%s)\n",
2514 +                        code, error_message(code));
2515 +       return (code);
2516 +}
2517 +
2518 +/*
2519   * We really shouldn't know about glue-layer context structure, but
2520   * we need to get at the real krb5 context pointer.  This should be
2521   * removed as soon as we say there is no support for MIT Kerberos
2522 @@ -154,48 +272,124 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
2523  {
2524         krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
2525         char *p, *end;
2526 -       static int constant_one = 1;
2527         static int constant_zero = 0;
2528 +       static int constant_one = 1;
2529 +       static int constant_two = 2;
2530         uint32_t word_seq_send;
2531 +       u_int64_t seq_send_64bit;
2532 +       uint32_t v2_flags = 0;
2533 +       krb5_keyblock derived_key;
2534 +       uint32_t numkeys;
2535  
2536         if (!(buf->value = calloc(1, MAX_CTX_LEN)))
2537                 goto out_err;
2538         p = buf->value;
2539         end = buf->value + MAX_CTX_LEN;
2540  
2541 -       if (kctx->initiate) {
2542 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2543 -       }
2544 -       else {
2545 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2546 -       }
2547 -       if (kctx->seed_init) {
2548 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2549 -       }
2550 -       else {
2551 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2552 -       }
2553 -       if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
2554 +       switch (kctx->sealalg) {
2555 +       case SEAL_ALG_DES:
2556 +               /* Old format of context to the kernel */
2557 +               if (kctx->initiate) {
2558 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2559 +               }
2560 +               else {
2561 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2562 +               }
2563 +               if (kctx->seed_init) {
2564 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2565 +               }
2566 +               else {
2567 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2568 +               }
2569 +               if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
2570 +                       goto out_err;
2571 +               if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
2572 +               if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
2573 +               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2574 +               word_seq_send = kctx->seq_send;
2575 +               if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
2576 +               if (write_oid(&p, end, kctx->mech_used)) goto out_err;
2577 +
2578 +               printerr(2, "serialize_krb5_ctx: serializing keys with "
2579 +                        "enctype %d and length %d\n",
2580 +                        kctx->enc->enctype, kctx->enc->length);
2581 +
2582 +               if (write_keyblock(&p, end, kctx->enc)) goto out_err;
2583 +               if (write_keyblock(&p, end, kctx->seq)) goto out_err;
2584 +               break;
2585 +       case SEAL_ALG_MICROSOFT_RC4:
2586 +       case SEAL_ALG_DES3KD:
2587 +               /* New format of context to the kernel */
2588 +               /* s32 endtime;
2589 +                * u32 flags;
2590 +                * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
2591 +                * #define KRB5_CTX_FLAG_CFX              0x00000002
2592 +                * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
2593 +                * u64 seq_send;
2594 +                * u32  enctype;
2595 +                * u32  size_of_each_key;    (  size in bytes )
2596 +                * u32  number_of_keys;      (  N (assumed to be 3 for now) )
2597 +                * keydata-1;                (  Ke  (Kenc for DES3) )
2598 +                * keydata-2;                (  Ki  (Kseq for DES3) )
2599 +                * keydata-3;                (  Kc (derived checksum key) )
2600 +                */
2601 +               if (kctx->initiate) {
2602 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
2603 +               }
2604 +               else {
2605 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
2606 +               }
2607 +               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2608 +
2609 +               /* Only applicable flag for this is initiator */
2610 +               if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
2611 +               if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
2612 +
2613 +               seq_send_64bit = kctx->seq_send;
2614 +               if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
2615 +
2616 +               if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
2617 +               if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
2618 +               numkeys = 3;
2619 +               if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
2620 +               printerr(2, "serialize_krb5_ctx: serializing %d keys with "
2621 +                        "enctype %d and size %d\n",
2622 +                        numkeys, kctx->enc->enctype, kctx->enc->length);
2623 +
2624 +               /* Ke */
2625 +               if (write_bytes(&p, end, kctx->enc->contents,
2626 +                               kctx->enc->length))
2627 +                       goto out_err;
2628 +
2629 +               /* Ki */
2630 +               if (write_bytes(&p, end, kctx->enc->contents,
2631 +                               kctx->enc->length))
2632 +                       goto out_err;
2633 +
2634 +               /* Kc */
2635 +               if (derive_key(kctx->seq, &derived_key,
2636 +                              KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
2637 +                       goto out_err;
2638 +               if (write_bytes(&p, end, derived_key.contents,
2639 +                               derived_key.length))
2640 +                       goto out_err;
2641 +               free(derived_key.contents);
2642 +               break;
2643 +       default:
2644 +               printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
2645 +                        "algorithm %d\n", kctx->sealalg);
2646                 goto out_err;
2647 -       if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
2648 -       if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
2649 -       if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
2650 -       word_seq_send = kctx->seq_send;
2651 -       if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
2652 -       if (write_oid(&p, end, kctx->mech_used)) goto out_err;
2653 -
2654 -       printerr(2, "serialize_krb5_ctx: serializing keys with "
2655 -                "enctype %d and length %d\n",
2656 -                kctx->enc->enctype, kctx->enc->length);
2657 -
2658 -       if (write_keyblock(&p, end, kctx->enc)) goto out_err;
2659 -       if (write_keyblock(&p, end, kctx->seq)) goto out_err;
2660 +       }
2661  
2662         buf->length = p - (char *)buf->value;
2663         return 0;
2664 +
2665  out_err:
2666         printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
2667 -       if (buf->value) free(buf->value);
2668 +       if (buf->value) {
2669 +               free(buf->value);
2670 +       }
2671 +       buf->value = NULL;
2672         buf->length = 0;
2673         return -1;
2674  }
This page took 0.366473 seconds and 3 git commands to generate.