]> git.pld-linux.org Git - packages/nfs-utils.git/blame - nfs-utils-CITI_NFS4.patch
- based on nfs-utils-1.0.11-CITI_NFS4_ALL-1.dif, adapted for 1.0.12
[packages/nfs-utils.git] / nfs-utils-CITI_NFS4.patch
CommitLineData
97cc26d8
JB
1
2
3The complete set of CITI nfs-utils patches rolled into one patch.
4
5Changes 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 }
355diff -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
379diff -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+}
571diff -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 */
625diff -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);
650diff -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;
668diff -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. */
757diff -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:
789diff -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;
1140diff -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 */
1154diff -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 }
1265diff -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;
1285diff -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,
1447diff -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;
1459diff -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");
1507diff -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;
1520diff -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);
1535diff -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);
1586diff -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);
1616diff -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+}
1886diff -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);
1898diff -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);
1919diff -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 */
2369diff -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.409286 seconds and 4 git commands to generate.