]> git.pld-linux.org Git - packages/nfs-utils.git/blame - nfs-utils-CITI_NFS4.patch
- update/clean TODO
[packages/nfs-utils.git] / nfs-utils-CITI_NFS4.patch
CommitLineData
71f23813 1Add secinfo processing.
97cc26d8 2
71f23813 3From: Fred Isaman <iisaman@citi.umich.edu>
97cc26d8 4
71f23813 5Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
97cc26d8 6
71f23813
JR
7Add secinfo processing.
8---
9
10 support/include/nfslib.h | 6 ++
11 support/nfs/exports.c | 145 ++++++++++++++++++++++++++++++++++++++++++++-
12 utils/exportfs/exportfs.c | 3 +
13 utils/mountd/cache.c | 14 ++++
14 4 files changed, 164 insertions(+), 4 deletions(-)
15
16Try to use kernel function to determine supported Kerberos enctypes.
97cc26d8 17
71f23813
JR
18From: Kevin Coffman <kwc@citi.umich.edu>
19
20Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
21
22This patch replaces a hard-coded list with a function to obtain
23the Kerberos encryption types that the kernel's rpcsec_gss code
24can support. Defaults to old behavior if kernel does not supply
25information.
26---
97cc26d8 27
71f23813
JR
28 utils/gssd/gssd.c | 2
29 utils/gssd/krb5_util.c | 228 +++++++++++++++++++++++++++++++++++++-----------
30 utils/gssd/krb5_util.h | 2
31 3 files changed, 182 insertions(+), 50 deletions(-)
97cc26d8 32
71f23813 33Add EXPERIMENTAL support for non-DES encryption types.
97cc26d8 34
71f23813 35From: Kevin Coffman <kwc@citi.umich.edu>
97cc26d8 36
71f23813 37Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
97cc26d8 38
71f23813
JR
39Adds EXPERIMENTAL support for non-DES encryption types. Sends a new
40format of context information to the kernel.
41(Requires kernel support to do anything useful.)
97cc26d8
JB
42---
43
71f23813
JR
44 utils/gssd/context.h | 6 +
45 utils/gssd/context_lucid.c | 391 ++++++++++++++++++++++++++++++++++++++++++--
46 utils/gssd/context_mit.c | 254 +++++++++++++++++++++++++----
47 3 files changed, 603 insertions(+), 48 deletions(-)
97cc26d8 48
71f23813
JR
49diff --git a/support/include/nfslib.h b/support/include/nfslib.h
50index c085029..6d7743d 100644
51--- a/support/include/nfslib.h
52+++ b/support/include/nfslib.h
53@@ -57,6 +57,9 @@ enum cle_maptypes {
54 #define _PATH_PROC_EXPORTS_ALT "/proc/fs/nfsd/exports"
55 #endif
97cc26d8 56
71f23813
JR
57+#define SECFLAVOR_COUNT 7
58+extern char *secflavor_name[SECFLAVOR_COUNT];
97cc26d8 59+
71f23813
JR
60 /*
61 * Data related to a single exports entry as returned by getexportent.
62 * FIXME: export options should probably be parsed at a later time to
63@@ -83,6 +86,8 @@ struct exportent {
64 int e_fslocmethod;
65 char * e_fslocdata;
66 char * e_uuid;
67+ int e_secinfo_order[SECFLAVOR_COUNT+1];
68+ int e_secinfo_flags[SECFLAVOR_COUNT];
69 };
70
71 struct rmtabent {
72@@ -96,6 +101,7 @@ struct rmtabent {
73 */
74 void setexportent(char *fname, char *type);
75 struct exportent * getexportent(int,int);
76+void secinfo_show(FILE *fp, struct exportent *ep);
77 void putexportent(struct exportent *xep);
78 void endexportent(void);
79 struct exportent * mkexportent(char *hname, char *path, char *opts);
80diff --git a/support/nfs/exports.c b/support/nfs/exports.c
81index 294e1c9..af9ab2f 100644
82--- a/support/nfs/exports.c
83+++ b/support/nfs/exports.c
84@@ -51,6 +51,10 @@ static int parsenum(char **cpp);
85 static int parsenum(char **cpp);
97cc26d8
JB
86 static void freesquash(void);
87 static void syntaxerr(char *msg);
88+static unsigned int parse_flavors(char *str, struct exportent *ep);
89+static int secinfo_default(struct exportent *ep);
90+static void setflags(int mask, unsigned int *ap, struct exportent *ep);
91+static void clearflags(int mask, unsigned int *ap, struct exportent *ep);
92
93 void
94 setexportent(char *fname, char *type)
71f23813 95@@ -102,6 +106,7 @@ getexportent(int fromkernel, int fromexp
97cc26d8
JB
96 def_ee.e_mountpoint = NULL;
97 def_ee.e_fslocmethod = FSLOC_NONE;
98 def_ee.e_fslocdata = NULL;
99+ def_ee.e_secinfo_order[0] = -1;
100 def_ee.e_nsquids = 0;
101 def_ee.e_nsqgids = 0;
102
71f23813 103@@ -182,6 +187,19 @@ getexportent(int fromkernel, int fromexp
97cc26d8
JB
104 }
105
106 void
107+secinfo_show(FILE *fp, struct exportent *ep)
108+{
109+ int *p1, *p2;
110+ for (p1=ep->e_secinfo_order; *p1>=0; p1=p2) {
111+ fprintf(fp, ",sec=%s", secflavor_name[*p1]);
112+ for (p2=p1+1; (*p2>=0) && (ep->e_secinfo_flags[*p1]==ep->e_secinfo_flags[*p2]); p2++) {
113+ fprintf(fp, ":%s", secflavor_name[*p2]);
114+ }
115+ fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw");
116+ }
117+}
118+
119+void
120 putexportent(struct exportent *ep)
121 {
122 FILE *fp;
71f23813 123@@ -199,7 +217,6 @@ putexportent(struct exportent *ep)
97cc26d8
JB
124 fprintf(fp, "%c", esc[i]);
125
126 fprintf(fp, "\t%s(", ep->e_hostname);
127- fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
128 fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
129 fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
130 "" : "no_");
71f23813 131@@ -276,7 +293,9 @@ #endif
97cc26d8
JB
132 else
133 fprintf(fp, "%d,", id[i]);
134 }
135- fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid);
136+ fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
137+ secinfo_show(fp, ep);
138+ fprintf(fp, ")\n");
139 }
140
141 void
71f23813 142@@ -325,6 +344,7 @@ mkexportent(char *hname, char *path, cha
97cc26d8
JB
143 ee.e_mountpoint = NULL;
144 ee.e_fslocmethod = FSLOC_NONE;
145 ee.e_fslocdata = NULL;
146+ ee.e_secinfo_order[0] = -1;
147 ee.e_nsquids = 0;
148 ee.e_nsqgids = 0;
149 ee.e_uuid = NULL;
71f23813 150@@ -376,6 +396,9 @@ parseopts(char *cp, struct exportent *ep
97cc26d8
JB
151 int had_subtree_opt = 0;
152 char *flname = efname?efname:"command line";
153 int flline = efp?efp->x_line:0;
154+ int *p;
155+ unsigned int active = 0;
156+ int secmask = NFSEXP_READONLY; /* options that can vary per flavor */
157
158 squids = ep->e_squids; nsquids = ep->e_nsquids;
159 sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
71f23813 160@@ -398,9 +421,9 @@ parseopts(char *cp, struct exportent *ep
97cc26d8
JB
161
162 /* process keyword */
163 if (strcmp(opt, "ro") == 0)
164- ep->e_flags |= NFSEXP_READONLY;
165+ setflags(NFSEXP_READONLY, &active, ep);
166 else if (strcmp(opt, "rw") == 0)
167- ep->e_flags &= ~NFSEXP_READONLY;
168+ clearflags(NFSEXP_READONLY, &active, ep);
169 else if (!strcmp(opt, "secure"))
170 ep->e_flags &= ~NFSEXP_INSECURE_PORT;
171 else if (!strcmp(opt, "insecure"))
71f23813 172@@ -522,6 +545,10 @@ #endif
97cc26d8
JB
173 } else if (strncmp(opt, "replicas=", 9) == 0) {
174 ep->e_fslocmethod = FSLOC_REPLICA;
175 ep->e_fslocdata = strdup(opt+9);
176+ } else if (strncmp(opt, "sec=", 4) == 0) {
177+ active = parse_flavors(opt+4, ep);
178+ if (!active)
179+ goto bad_option;
180 } else {
181 xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
182 flname, flline, opt);
71f23813 183@@ -533,6 +560,12 @@ #endif
97cc26d8
JB
184 cp++;
185 }
186
187+ if (!active)
188+ active = secinfo_default(ep);
189+ for (p=ep->e_secinfo_order; *p>=0; p++)
190+ ep->e_secinfo_flags[*p] |= (ep->e_flags & ~secmask);
191+ /* If did not use sec= option, ensure e_flags is backward compatible */
192+ ep->e_flags = ep->e_secinfo_flags[ep->e_secinfo_order[0]];
193 ep->e_squids = squids;
194 ep->e_sqgids = sqgids;
195 ep->e_nsquids = nsquids;
71f23813 196@@ -663,3 +696,107 @@ syntaxerr(char *msg)
97cc26d8
JB
197 efname, efp?efp->x_line:0, msg);
198 }
199
200+char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
201+ "krb5",
202+ "krb5i",
203+ "krb5p",
204+ "spkm3",
205+ "spkm3i",
206+ "spkm3p"
207+};
208+
209+static void
210+secinfo_addflavor(int bit, struct exportent *ep)
211+{
212+ int *p;
213+ for (p=ep->e_secinfo_order; *p>=0; p++) {
214+ if (*p == bit)
215+ return;
216+ }
217+ *p++ = bit;
218+ *p = -1;
219+ ep->e_secinfo_flags[bit] = 0;
220+}
221+
222+static int
223+secinfo_nameindex(char *name)
224+{
225+ int i;
226+ for (i=0; i<SECFLAVOR_COUNT; i++) {
227+ if (strcmp(secflavor_name[i], name) == 0)
228+ return i;
229+ }
230+ return -1;
231+}
232+
233+/* @str is a colon seperated list of security flavors. Their order
234+ * is recorded in @ep, and a bitmap corresponding to the list is returned.
235+ * A zero return indicates an error.
236+ */
237+static unsigned int
238+parse_flavors(char *str, struct exportent *ep)
239+{
240+ unsigned int out=0;
241+ char *flavor;
242+ int bit;
243+
244+ while ( (flavor=strsep(&str, ":")) ) {
245+ bit = secinfo_nameindex(flavor);
246+ if (bit == -1) {
247+ xlog(L_ERROR, "unknown flavor %s\n", flavor);
248+ return 0;
249+ }
250+ out |= 1<<bit;
251+ secinfo_addflavor(bit, ep);
252+ }
253+ return out;
254+}
255+
256+/* Determine a default security flavor based on ep->e_hostname. */
257+static int
258+secinfo_default(struct exportent *ep)
259+{
260+ int i=-1;
261+ if (strncmp(ep->e_hostname, "gss/", 4) == 0) {
262+ i = secinfo_nameindex(ep->e_hostname + 4);
263+ if (i < 0)
264+ xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname);
265+ }
266+ /* Default to auth_sys */
267+ if (i < 0)
268+ i = secinfo_nameindex("sys");
269+ secinfo_addflavor(i, ep);
270+ return 1<<i;
271+}
272+
273+/* Sets the bits in @mask for the appropriate security flavor flags. */
274+static void
275+setflags(int mask, unsigned int *ap, struct exportent *ep)
276+{
277+ int active, flavor=0;
278+ if (!*ap)
279+ *ap = secinfo_default(ep);
280+ active = *ap;
281+ while (active) {
282+ if (active & 1)
283+ ep->e_secinfo_flags[flavor] |= mask;
284+ flavor++;
285+ active >>= 1;
286+ }
287+}
288+
289+/* Clears the bits in @mask for the appropriate security flavor flags. */
290+static void
291+clearflags(int mask, unsigned int *ap, struct exportent *ep)
292+{
293+ int active, flavor=0;
294+ if (!*ap)
295+ *ap = secinfo_default(ep);
296+ active = *ap;
297+ while (active) {
298+ if (active & 1)
299+ ep->e_secinfo_flags[flavor] &= ~mask;
300+ flavor++;
301+ active >>= 1;
302+ }
303+}
71f23813
JR
304diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
305index 22e13a3..30732b8 100644
306--- a/utils/exportfs/exportfs.c
307+++ b/utils/exportfs/exportfs.c
308@@ -376,10 +376,12 @@ dump(int verbose)
97cc26d8
JB
309 continue;
310 }
311 c = '(';
312+ /*
313 if (ep->e_flags & NFSEXP_READONLY)
314 c = dumpopt(c, "ro");
315 else
316 c = dumpopt(c, "rw");
317+ */
318 if (ep->e_flags & NFSEXP_ASYNC)
319 c = dumpopt(c, "async");
320 if (ep->e_flags & NFSEXP_GATHERED_WRITES)
71f23813 321@@ -433,6 +435,7 @@ #ifdef DEBUG
97cc26d8
JB
322 break;
323 #endif
324 }
325+ secinfo_show(stdout, ep);
326 printf("%c\n", (c != '(')? ')' : ' ');
327 }
328 }
71f23813
JR
329diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
330index 5f0d12a..78a8f75 100644
331--- a/utils/mountd/cache.c
332+++ b/utils/mountd/cache.c
333@@ -445,6 +445,19 @@ static void write_fsloc(FILE *f, struct
334 release_replicas(servers);
97cc26d8
JB
335 }
336
71f23813 337+static void write_secinfo(FILE *f, struct exportent *ep)
97cc26d8 338+{
71f23813
JR
339+ int *p;
340+ qword_print(f, "secinfo");
341+ for (p=ep->e_secinfo_order; *p>=0; p++)
342+ ; /* Do nothing */
343+ qword_printint(f, p - ep->e_secinfo_order);
344+ for (p=ep->e_secinfo_order; *p>=0; p++) {
345+ qword_print(f, secflavor_name[*p]);
346+ qword_printint(f, ep->e_secinfo_flags[*p]);
97cc26d8 347+ }
97cc26d8
JB
348+}
349+
71f23813 350 static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
97cc26d8 351 {
71f23813
JR
352 qword_print(f, domain);
353@@ -466,6 +479,7 @@ static int dump_to_cache(FILE *f, char *
354 qword_printhex(f, exp->e_uuid, 16);
355 }
97cc26d8 356 #endif
71f23813 357+ write_secinfo(f, exp);
97cc26d8 358 }
71f23813 359 return qword_eol(f);
97cc26d8 360 }
71f23813
JR
361diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
362index 08a6c10..44afdd0 100644
363--- a/utils/gssd/gssd.c
364+++ b/utils/gssd/gssd.c
365@@ -162,6 +162,8 @@ #endif
97cc26d8 366 /* Process keytab file and get machine credentials */
71f23813
JR
367 if (root_uses_machine_creds)
368 gssd_refresh_krb5_machine_creds();
97cc26d8
JB
369+ /* Determine Kerberos information from the kernel */
370+ gssd_obtain_kernel_krb5_info();
371
372 gssd_run();
373 printerr(0, "gssd_run returned!\n");
71f23813
JR
374diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
375index 096f6cf..96e91ae 100644
376--- a/utils/gssd/krb5_util.c
377+++ b/utils/gssd/krb5_util.c
378@@ -97,6 +97,7 @@ #endif
97cc26d8
JB
379 #include "config.h"
380 #include <sys/param.h>
381 #include <rpc/rpc.h>
382+#include <sys/types.h>
383 #include <sys/stat.h>
384 #include <sys/socket.h>
385 #include <arpa/inet.h>
71f23813 386@@ -105,6 +106,7 @@ #include <stdio.h>
97cc26d8
JB
387 #include <stdlib.h>
388 #include <string.h>
389 #include <dirent.h>
390+#include <fcntl.h>
391 #include <errno.h>
392 #include <time.h>
393 #include <gssapi/gssapi.h>
71f23813 394@@ -123,6 +125,10 @@ #include "krb5_util.h"
97cc26d8
JB
395 /* Global list of principals/cache file names for machine credentials */
396 struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
397
398+/* Encryption types supported by the kernel rpcsec_gss code */
399+int num_krb5_enctypes = 0;
400+krb5_enctype *krb5_enctypes = NULL;
401+
402 /*==========================*/
403 /*=== Internal routines ===*/
404 /*==========================*/
405@@ -256,56 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
406 }
407
408
409-#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
410-/*
411- * this routine obtains a credentials handle via gss_acquire_cred()
412- * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
413- * types negotiated.
414- *
415- * XXX Should call some function to determine the enctypes supported
416- * by the kernel. (Only need to do that once!)
417- *
418- * Returns:
419- * 0 => all went well
420- * -1 => there was an error
421- */
422-
423-int
424-limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
425-{
426- u_int maj_stat, min_stat;
427- gss_cred_id_t credh;
428- gss_OID_set_desc desired_mechs;
429- krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
430- int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
431-
432- /* We only care about getting a krb5 cred */
433- desired_mechs.count = 1;
434- desired_mechs.elements = &krb5oid;
435-
436- maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
437- &desired_mechs, GSS_C_INITIATE,
438- &credh, NULL, NULL);
439-
440- if (maj_stat != GSS_S_COMPLETE) {
441- pgsserr("gss_acquire_cred",
442- maj_stat, min_stat, &krb5oid);
443- return -1;
444- }
445-
446- maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
447- num_enctypes, &enctypes);
448- if (maj_stat != GSS_S_COMPLETE) {
449- pgsserr("gss_set_allowable_enctypes",
450- maj_stat, min_stat, &krb5oid);
451- return -1;
452- }
453- sec->cred = credh;
454-
455- return 0;
456-}
457-#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
458-
459 /*
460 * Obtain credentials via a key in the keytab given
461 * a keytab handle and a gssd_k5_kt_princ structure.
71f23813 462@@ -609,6 +565,56 @@ #else
97cc26d8
JB
463 #endif
464 }
465
466+/*
467+ * Parse the supported encryption type information
468+ */
469+static int
470+parse_enctypes(char *enctypes)
471+{
472+ int n = 0;
473+ char *curr, *comma;
474+ int i;
475+
476+ /* Just in case this ever gets called more than once */
477+ if (krb5_enctypes != NULL) {
478+ free(krb5_enctypes);
479+ krb5_enctypes = NULL;
480+ num_krb5_enctypes = 0;
481+ }
482+
483+ /* count the number of commas */
484+ for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
485+ comma = strchr(curr, ',');
486+ if (comma != NULL)
487+ n++;
488+ else
489+ break;
490+ }
491+ /* If no more commas and we're not at the end, there's one more value */
492+ if (*curr != '\0')
493+ n++;
494+
495+ /* Empty string, return an error */
496+ if (n == 0)
497+ return ENOENT;
498+
499+ /* Allocate space for enctypes array */
500+ if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
501+ return ENOMEM;
502+ }
503+
504+ /* Now parse each value into the array */
505+ for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
506+ krb5_enctypes[i++] = atoi(curr);
507+ comma = strchr(curr, ',');
508+ if (comma == NULL)
509+ break;
510+ }
511+
512+ num_krb5_enctypes = n;
513+ return 0;
514+}
515+
516 /*==========================*/
517 /*=== External routines ===*/
518 /*==========================*/
519@@ -860,3 +866,125 @@ gssd_destroy_krb5_machine_creds(void)
520 krb5_free_context(context);
521 }
522
523+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
524+/*
525+ * this routine obtains a credentials handle via gss_acquire_cred()
526+ * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
527+ * types negotiated.
528+ *
529+ * Returns:
530+ * 0 => all went well
531+ * -1 => there was an error
532+ */
533+
534+int
535+limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
536+{
537+ u_int maj_stat, min_stat;
538+ gss_cred_id_t credh;
539+ gss_OID_set_desc desired_mechs;
540+ krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
541+ int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
542+
543+ /* We only care about getting a krb5 cred */
544+ desired_mechs.count = 1;
545+ desired_mechs.elements = &krb5oid;
546+
547+ maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
548+ &desired_mechs, GSS_C_INITIATE,
549+ &credh, NULL, NULL);
550+
551+ if (maj_stat != GSS_S_COMPLETE) {
552+ pgsserr("gss_acquire_cred",
553+ maj_stat, min_stat, &krb5oid);
554+ return -1;
555+ }
556+
557+ /*
558+ * If we failed for any reason to produce global
559+ * list of supported enctypes, use local default here.
560+ */
561+ if (krb5_enctypes == NULL)
562+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
563+ &krb5oid, num_enctypes, &enctypes);
564+ else
565+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
566+ &krb5oid, num_krb5_enctypes,
567+ krb5_enctypes);
568+ if (maj_stat != GSS_S_COMPLETE) {
569+ pgsserr("gss_set_allowable_enctypes",
570+ maj_stat, min_stat, &krb5oid);
571+ return -1;
572+ }
573+ sec->cred = credh;
574+
575+ return 0;
576+}
577+#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
578+
579+/*
580+ * Obtain supported enctypes from kernel.
581+ * Set defaults if info is not available.
582+ */
583+void
584+gssd_obtain_kernel_krb5_info(void)
585+{
586+ char enctype_file_name[128];
587+ char buf[1024];
588+ char enctypes[128];
589+ int nscanned;
590+ int fd;
591+ int use_default_enctypes = 0;
592+ int nbytes, numfields;
593+ char default_enctypes[] = "1,3,2";
594+ int code;
595+
596+ snprintf(enctype_file_name, sizeof(enctype_file_name),
597+ "%s/%s", pipefs_dir, "krb5_info");
598+
599+ if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
600+ printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
601+ "Unable to open '%s'. Unable to determine "
602+ "Kerberos encryption types supported by the "
603+ "kernel; using defaults (%s).\n",
604+ enctype_file_name, default_enctypes);
605+ use_default_enctypes = 1;
606+ goto do_the_parse;
607+ }
608+ memset(buf, 0, sizeof(buf));
609+ if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) {
610+ printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
611+ "Error reading Kerberos encryption type "
612+ "information file '%s'; using defaults (%s).\n",
613+ enctype_file_name, default_enctypes);
614+ use_default_enctypes = 1;
615+ close(fd);
616+ goto do_the_parse;
617+ }
618+ close(fd);
619+ numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned);
620+ if (numfields < 1) {
621+ printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
622+ "error parsing Kerberos encryption type "
623+ "information from file '%s'; using defaults (%s).\n",
624+ enctype_file_name, default_enctypes);
625+ use_default_enctypes = 1;
626+ goto do_the_parse;
627+ }
628+ if (nbytes > nscanned) {
629+ printerr(2, "gssd_obtain_kernel_krb5_info: "
630+ "Ignoring extra information, '%s', from '%s'\n",
631+ buf+nscanned, enctype_file_name);
632+ goto do_the_parse;
633+ }
634+ do_the_parse:
635+ if (use_default_enctypes)
636+ strcpy(enctypes, default_enctypes);
637+
638+ if ((code = parse_enctypes(enctypes)) != 0) {
639+ printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
640+ "parse_enctypes%s failed with code %d\n",
641+ use_default_enctypes ? " (with default enctypes)" : "",
642+ code);
643+ }
644+}
71f23813
JR
645diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
646index da04530..2af1a25 100644
647--- a/utils/gssd/krb5_util.h
648+++ b/utils/gssd/krb5_util.h
97cc26d8
JB
649@@ -22,6 +22,8 @@ int gssd_refresh_krb5_machine_creds(voi
650 void gssd_free_krb5_machine_cred_list(char **list);
651 void gssd_setup_krb5_machine_gss_ccache(char *servername);
652 void gssd_destroy_krb5_machine_creds(void);
653+void gssd_obtain_kernel_krb5_info(void);
654+
655
656 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
657 int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
71f23813
JR
658diff --git a/utils/gssd/context.h b/utils/gssd/context.h
659index 67ed3bb..68b0c11 100644
660--- a/utils/gssd/context.h
661+++ b/utils/gssd/context.h
97cc26d8
JB
662@@ -1,5 +1,5 @@
663 /*
664- Copyright (c) 2004 The Regents of the University of Michigan.
665+ Copyright (c) 2004-2006 The Regents of the University of Michigan.
666 All rights reserved.
667
668 Redistribution and use in source and binary forms, with or without
71f23813 669@@ -36,6 +36,10 @@ #include <rpc/rpc.h>
97cc26d8
JB
670 /* Hopefully big enough to hold any serialized context */
671 #define MAX_CTX_LEN 4096
672
673+/* New context format flag values */
674+#define KRB5_CTX_FLAG_INITIATOR 0x00000001
675+#define KRB5_CTX_FLAG_CFX 0x00000002
676+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
677
678 int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
679 gss_OID mech);
71f23813
JR
680diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
681index 3550762..c824dcd 100644
682--- a/utils/gssd/context_lucid.c
683+++ b/utils/gssd/context_lucid.c
684@@ -40,6 +40,7 @@ #ifdef HAVE_LUCID_CONTEXT_SUPPORT
97cc26d8
JB
685 #include <stdio.h>
686 #include <syslog.h>
687 #include <string.h>
688+#include <errno.h>
689 #include "gss_util.h"
690 #include "gss_oids.h"
691 #include "err_util.h"
71f23813 692@@ -113,15 +114,13 @@ #ifdef HAVE_HEIMDAL
97cc26d8
JB
693 * Note that the rfc1964 version only supports DES enctypes.
694 */
695 if (lctx->rfc1964_kd.ctx_key.type != 4) {
696- printerr(1, "prepare_krb5_rfc1964_buffer: "
697- "overriding heimdal keytype (%d => %d)\n",
698- lctx->rfc1964_kd.ctx_key.type, 4);
699+ printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
700+ __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
701 lctx->rfc1964_kd.ctx_key.type = 4;
702 }
703 #endif
704- printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
705- "enctype %d and length %d\n",
706- lctx->rfc1964_kd.ctx_key.type,
707+ printerr(2, "%s: serializing keys with enctype %d and length %d\n",
708+ __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
709 lctx->rfc1964_kd.ctx_key.length);
710
711 /* derive the encryption key and copy it into buffer */
712@@ -152,15 +151,361 @@ out_err:
713 return -1;
714 }
715
716-static int
717-prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
718- gss_buffer_desc *buf)
719+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
720+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
721+
722+/* for 3DES */
723+#define KG_USAGE_SEAL 22
724+#define KG_USAGE_SIGN 23
725+#define KG_USAGE_SEQ 24
726+
727+/* for rfc???? */
728+#define KG_USAGE_ACCEPTOR_SEAL 22
729+#define KG_USAGE_ACCEPTOR_SIGN 23
730+#define KG_USAGE_INITIATOR_SEAL 24
731+#define KG_USAGE_INITIATOR_SIGN 25
732+
733+/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
734+enum seal_alg {
735+ SEAL_ALG_NONE = 0xffff,
736+ SEAL_ALG_DES = 0x0000,
737+ SEAL_ALG_1 = 0x0001, /* not published */
738+ SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
739+ SEAL_ALG_DES3KD = 0x0002
740+};
741+
742+#define KEY_USAGE_SEED_ENCRYPTION 0xAA
743+#define KEY_USAGE_SEED_INTEGRITY 0x55
744+#define KEY_USAGE_SEED_CHECKSUM 0x99
745+#define K5CLENGTH 5
746+
747+/* Flags for version 2 context flags */
748+#define KRB5_CTX_FLAG_INITIATOR 0x00000001
749+#define KRB5_CTX_FLAG_CFX 0x00000002
750+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
751+
752+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
753+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
754+/*
755+ * We don't have "legal" access to these MIT-only
756+ * structures located in libk5crypto
757+ */
758+extern void krb5int_enc_arcfour;
759+extern void krb5int_enc_des3;
760+extern void krb5int_enc_aes128;
761+extern void krb5int_enc_aes256;
762+extern int krb5_derive_key();
763+
764+static void
765+key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
766 {
767- printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
768- return -1;
769+ memset(kout, '\0', sizeof(kout));
770+#ifdef HAVE_KRB5
771+ kout->enctype = lin->type;
772+ kout->length = lin->length;
773+ kout->contents = lin->data;
774+#else
775+ kout->keytype = lin->type;
776+ kout->keyvalue.length = lin->length;
777+ kout->keyvalue.data = lin->data;
778+#endif
71f23813
JR
779+}
780+
97cc26d8
JB
781+static void
782+key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
783+{
784+ memset(lout, '\0', sizeof(lout));
785+#ifdef HAVE_KRB5
786+ lout->type = kin->enctype;
787+ lout->length = kin->length;
788+ lout->data = kin->contents;
789+#else
790+ lout->type = kin->keytype;
791+ lout->length = kin->keyvalue.length;
792+ memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
793+#endif
794+}
71f23813 795+
97cc26d8
JB
796+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
797+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
798+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
799+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
800+/*
801+ * Function to derive a new key from a given key and given constant data.
802+ */
803+static krb5_error_code
804+derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
805+ int usage, char extra)
806+{
807+ krb5_error_code code;
808+ unsigned char constant_data[K5CLENGTH];
809+ krb5_data datain;
810+ int keylength;
811+ void *enc;
812+ krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
813+#ifdef HAVE_HEIMDAL
814+ krb5_context kcontext;
815+ krb5_keyblock *outkey;
816+#endif
817+
818+ /*
819+ * XXX Hack alert. We don't have "legal" access to these
820+ * values and structures located in libk5crypto
821+ */
822+ switch (in->type) {
823+ case ENCTYPE_DES3_CBC_SHA1:
824+#ifdef HAVE_KRB5
825+ case ENCTYPE_DES3_CBC_RAW:
826+#endif
827+ keylength = 24;
828+#ifdef HAVE_KRB5
829+ enc = &krb5int_enc_des3;
830+#endif
831+ break;
832+ case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
833+ keylength = 16;
834+#ifdef HAVE_KRB5
835+ enc = &krb5int_enc_aes128;
836+#endif
837+ break;
838+ case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
839+ keylength = 32;
840+#ifdef HAVE_KRB5
841+ enc = &krb5int_enc_aes256;
842+#endif
843+ break;
844+ default:
845+ code = KRB5_BAD_ENCTYPE;
846+ goto out;
847+ }
848+
849+ /* allocate memory for output key */
850+ if ((out->data = malloc(keylength)) == NULL) {
851+ code = ENOMEM;
852+ goto out;
853+ }
854+ out->length = keylength;
855+ out->type = in->type;
856+
857+ /* Convert to correct format for call to krb5_derive_key */
858+ key_lucid_to_krb5(in, &kin);
859+ key_lucid_to_krb5(out, &kout);
860+
861+ datain.data = (char *) constant_data;
862+ datain.length = K5CLENGTH;
863+
864+ ((char *)(datain.data))[0] = (usage>>24)&0xff;
865+ ((char *)(datain.data))[1] = (usage>>16)&0xff;
866+ ((char *)(datain.data))[2] = (usage>>8)&0xff;
867+ ((char *)(datain.data))[3] = usage&0xff;
868+
869+ ((char *)(datain.data))[4] = (char) extra;
870+
871+#ifdef HAVE_KRB5
872+ code = krb5_derive_key(enc, &kin, &kout, &datain);
873+#else
874+ if ((code = krb5_init_context(&kcontext))) {
875+ }
876+ code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
877+#endif
878+ if (code) {
879+ free(out->data);
880+ out->data = NULL;
881+ goto out;
882+ }
883+#ifdef HAVE_KRB5
884+ key_krb5_to_lucid(&kout, out);
885+#else
886+ key_krb5_to_lucid(outkey, out);
887+ krb5_free_keyblock(kcontext, outkey);
888+ krb5_free_context(kcontext);
889+#endif
890+
891+ out:
892+ if (code)
893+ printerr(0, "ERROR: %s: returning error %d (%s)\n",
894+ __FUNCTION__, code, error_message(code));
895+ return (code);
71f23813
JR
896 }
897
898
97cc26d8
JB
899+/*
900+ * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
901+ * to send to the kernel for newer encryption types -- or for DES3.
902+ *
903+ * The new format is:
904+ *
905+ * u32 initiate; ( whether we are the initiator or not )
906+ * s32 endtime;
907+ * u32 flags;
908+ * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
909+ * #define KRB5_CTX_FLAG_CFX 0x00000002
910+ * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
911+ * u64 seq_send;
912+ * u32 enctype; ( encrption type of keys )
913+ * u32 size_of_each_key; ( size of each key in bytes )
914+ * u32 number_of_keys; ( N -- should always be 3 for now )
915+ * keydata-1; ( Ke )
916+ * keydata-2; ( Ki )
917+ * keydata-3; ( Kc )
918+ *
919+ */
920+static int
921+prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
922+ gss_buffer_desc *buf)
923+{
924+ char *p, *end;
925+ uint32_t v2_flags = 0;
926+ gss_krb5_lucid_key_t enc_key;
927+ gss_krb5_lucid_key_t derived_key;
928+ gss_buffer_desc fakeoid;
929+ uint32_t enctype;
930+ uint32_t keysize;
931+ uint32_t numkeys;
932+
933+ memset(&enc_key, 0, sizeof(enc_key));
934+ memset(&fakeoid, 0, sizeof(fakeoid));
935+
936+ if (!(buf->value = calloc(1, MAX_CTX_LEN)))
937+ goto out_err;
938+ p = buf->value;
939+ end = buf->value + MAX_CTX_LEN;
940+
941+ /* Version 2 */
942+ if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
943+ if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
944+
945+ if (lctx->initiate)
946+ v2_flags |= KRB5_CTX_FLAG_INITIATOR;
947+ if (lctx->protocol != 0)
948+ v2_flags |= KRB5_CTX_FLAG_CFX;
949+ if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
950+ v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
951+
952+ if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
953+
954+ if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
955+
956+ /* Protocol 0 here implies DES3 or RC4 */
957+ printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
958+ if (lctx->protocol == 0) {
959+ enctype = lctx->rfc1964_kd.ctx_key.type;
960+#ifdef HAVE_HEIMDAL
961+ /*
962+ * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for
963+ * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16).
964+ * Force the Heimdal enctype to 6.
965+ */
966+ if (enctype == ENCTYPE_DES3_CBC_SHA1) {
967+ printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
968+ __FUNCTION__, enctype, 6);
969+
970+ enctype = 6;
971+ }
972+#endif
973+ keysize = lctx->rfc1964_kd.ctx_key.length;
974+ numkeys = 3; /* XXX is always gonna be three? */
975+ } else {
976+ if (lctx->cfx_kd.have_acceptor_subkey) {
977+ enctype = lctx->cfx_kd.acceptor_subkey.type;
978+ keysize = lctx->cfx_kd.acceptor_subkey.length;
979+ } else {
980+ enctype = lctx->cfx_kd.ctx_key.type;
981+ keysize = lctx->cfx_kd.ctx_key.length;
982+ }
983+ numkeys = 3;
984+ }
985+ printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
986+ __FUNCTION__, numkeys, enctype, keysize);
987+ if (WRITE_BYTES(&p, end, enctype)) goto out_err;
988+ if (WRITE_BYTES(&p, end, keysize)) goto out_err;
989+ if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
990+
991+ if (lctx->protocol == 0) {
992+ /* derive and send down: Ke, Ki, and Kc */
993+ /* Ke */
994+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
995+ lctx->rfc1964_kd.ctx_key.length))
996+ goto out_err;
997+
998+ /* Ki */
999+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
1000+ lctx->rfc1964_kd.ctx_key.length))
1001+ goto out_err;
1002+
1003+ /* Kc */
1004+ if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
1005+ &derived_key,
1006+ KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1007+ goto out_err;
1008+ if (write_bytes(&p, end, derived_key.data,
1009+ derived_key.length))
1010+ goto out_err;
1011+ free(derived_key.data);
1012+ } else {
1013+ gss_krb5_lucid_key_t *keyptr;
1014+ uint32_t sign_usage, seal_usage;
1015+
1016+ if (lctx->cfx_kd.have_acceptor_subkey)
1017+ keyptr = &lctx->cfx_kd.acceptor_subkey;
1018+ else
1019+ keyptr = &lctx->cfx_kd.ctx_key;
1020+
1021+ if (lctx->initiate == 1) {
1022+ sign_usage = KG_USAGE_INITIATOR_SIGN;
1023+ seal_usage = KG_USAGE_INITIATOR_SEAL;
1024+ } else {
1025+ sign_usage = KG_USAGE_ACCEPTOR_SIGN;
1026+ seal_usage = KG_USAGE_ACCEPTOR_SEAL;
1027+ }
1028+
1029+ /* derive and send down: Ke, Ki, and Kc */
1030+
1031+ /* Ke */
1032+ if (derive_key_lucid(keyptr, &derived_key,
1033+ seal_usage, KEY_USAGE_SEED_ENCRYPTION))
1034+ goto out_err;
1035+ if (write_bytes(&p, end, derived_key.data,
1036+ derived_key.length))
1037+ goto out_err;
1038+ free(derived_key.data);
1039+
1040+ /* Ki */
1041+ if (derive_key_lucid(keyptr, &derived_key,
1042+ seal_usage, KEY_USAGE_SEED_INTEGRITY))
1043+ goto out_err;
1044+ if (write_bytes(&p, end, derived_key.data,
1045+ derived_key.length))
1046+ goto out_err;
1047+ free(derived_key.data);
1048+
1049+ /* Kc */
1050+ if (derive_key_lucid(keyptr, &derived_key,
1051+ sign_usage, KEY_USAGE_SEED_CHECKSUM))
1052+ goto out_err;
1053+ if (write_bytes(&p, end, derived_key.data,
1054+ derived_key.length))
1055+ goto out_err;
1056+ free(derived_key.data);
1057+ }
1058+
1059+ buf->length = p - (char *)buf->value;
1060+ return 0;
1061+
1062+out_err:
1063+ printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
1064+ __FUNCTION__);
1065+ if (buf->value) {
1066+ free(buf->value);
1067+ buf->value = NULL;
1068+ }
1069+ buf->length = 0;
1070+ if (enc_key.data) {
1071+ free(enc_key.data);
1072+ enc_key.data = NULL;
1073+ }
1074+ return -1;
1075+}
1076 int
1077 serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
1078 {
1079@@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1080 gss_krb5_lucid_context_v1_t *lctx = 0;
1081 int retcode = 0;
1082
1083- printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
1084+ printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
1085 maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
1086 1, &return_ctx);
1087 if (maj_stat != GSS_S_COMPLETE) {
1088@@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1089 break;
1090 }
1091
1092- /* Now lctx points to a lucid context that we can send down to kernel */
1093- if (lctx->protocol == 0)
1094+ /*
1095+ * Now lctx points to a lucid context that we can send down to kernel
1096+ *
1097+ * Note: we send down different information to the kernel depending
1098+ * on the protocol version and the enctyption type.
1099+ * For protocol version 0 with all enctypes besides DES3, we use
1100+ * the original format. For protocol version != 0 or DES3, we
1101+ * send down the new style information.
1102+ */
1103+
1104+ if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
1105 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
1106 else
1107- retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
1108+ retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
1109
1110 maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
1111 if (maj_stat != GSS_S_COMPLETE) {
1112@@ -206,8 +560,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1113 }
1114
1115 if (retcode) {
1116- printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
1117- "failed (retcode = %d)\n", retcode);
1118+ printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
1119+ __FUNCTION__, retcode);
1120 goto out_err;
1121 }
1122
1123@@ -217,4 +571,7 @@ out_err:
1124 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
1125 return -1;
1126 }
1127+
1128+
1129+
1130 #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
71f23813
JR
1131diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
1132index 94b2266..cd6ab0f 100644
1133--- a/utils/gssd/context_mit.c
1134+++ b/utils/gssd/context_mit.c
97cc26d8
JB
1135@@ -1,5 +1,5 @@
1136 /*
1137- Copyright (c) 2004 The Regents of the University of Michigan.
1138+ Copyright (c) 2004-2006 The Regents of the University of Michigan.
1139 All rights reserved.
1140
1141 Redistribution and use in source and binary forms, with or without
71f23813 1142@@ -36,6 +36,7 @@ #ifdef HAVE_KRB5
97cc26d8
JB
1143 #include <stdio.h>
1144 #include <syslog.h>
1145 #include <string.h>
1146+#include <errno.h>
a32f8019 1147 #include <gssapi/gssapi.h>
97cc26d8
JB
1148 #include <rpc/rpc.h>
1149 #include <rpc/auth_gss.h>
71f23813 1150@@ -50,8 +51,7 @@ #if (KRB5_VERSION > 131)
97cc26d8
JB
1151 /* XXX argggg, there's gotta be a better way than just duplicating this
1152 * whole struct. Unfortunately, this is in a "private" header file,
1153 * so this is our best choice at this point :-/
1154- *
1155- * XXX Does this match the Heimdal definition? */
1156+ */
1157
1158 typedef struct _krb5_gss_ctx_id_rec {
1159 unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */
1160@@ -139,6 +139,124 @@ write_keyblock(char **p, char *end, stru
1161 }
1162
1163 /*
1164+ * XXX Hack alert! XXX Do NOT submit upstream!
1165+ * XXX Hack alert! XXX Do NOT submit upstream!
1166+ *
1167+ * We shouldn't be using these definitions
1168+ *
1169+ * XXX Hack alert! XXX Do NOT submit upstream!
1170+ * XXX Hack alert! XXX Do NOT submit upstream!
1171+ */
1172+/* for 3DES */
1173+#define KG_USAGE_SEAL 22
1174+#define KG_USAGE_SIGN 23
1175+#define KG_USAGE_SEQ 24
1176+
1177+/* for rfc???? */
1178+#define KG_USAGE_ACCEPTOR_SEAL 22
1179+#define KG_USAGE_ACCEPTOR_SIGN 23
1180+#define KG_USAGE_INITIATOR_SEAL 24
1181+#define KG_USAGE_INITIATOR_SIGN 25
1182+
1183+/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
1184+enum seal_alg {
1185+ SEAL_ALG_NONE = 0xffff,
1186+ SEAL_ALG_DES = 0x0000,
1187+ SEAL_ALG_1 = 0x0001, /* not published */
1188+ SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
1189+ SEAL_ALG_DES3KD = 0x0002
1190+};
1191+
1192+#define KEY_USAGE_SEED_ENCRYPTION 0xAA
1193+#define KEY_USAGE_SEED_INTEGRITY 0x55
1194+#define KEY_USAGE_SEED_CHECKSUM 0x99
1195+#define K5CLENGTH 5
1196+
1197+extern void krb5_enc_des3;
1198+extern void krb5int_enc_des3;
1199+extern void krb5int_enc_arcfour;
1200+extern void krb5int_enc_aes128;
1201+extern void krb5int_enc_aes256;
1202+extern int krb5_derive_key();
1203+
1204+/*
1205+ * XXX Hack alert! XXX Do NOT submit upstream!
1206+ * XXX Hack alert! XXX Do NOT submit upstream!
1207+ *
1208+ * We should be passing down a single key to the kernel
1209+ * and it should be deriving the other keys. We cannot
1210+ * depend on any of this stuff being accessible in the
1211+ * future.
1212+ *
1213+ * XXX Hack alert! XXX Do NOT submit upstream!
1214+ * XXX Hack alert! XXX Do NOT submit upstream!
1215+ */
1216+/*
1217+ * Function to derive a new key from a given key and given constant data.
1218+ */
1219+static krb5_error_code
1220+derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
1221+{
1222+ krb5_error_code code;
1223+ unsigned char constant_data[K5CLENGTH];
1224+ krb5_data datain;
1225+ int keylength;
1226+ void *enc;
1227+
1228+ switch (in->enctype) {
1229+#ifdef ENCTYPE_DES3_CBC_RAW
1230+ case ENCTYPE_DES3_CBC_RAW:
1231+ keylength = 24;
1232+/* Extra hack, the structure was renamed as rc4 was added... */
1233+#if defined(ENCTYPE_ARCFOUR_HMAC)
1234+ enc = &krb5int_enc_des3;
1235+#else
1236+ enc = &krb5_enc_des3;
1237+#endif
1238+ break;
1239+#endif
1240+#ifdef ENCTYPE_ARCFOUR_HMAC
1241+ case ENCTYPE_ARCFOUR_HMAC:
1242+ keylength = 16;
1243+ enc = &krb5int_enc_arcfour;
1244+ break;
1245+#endif
1246+ default:
1247+ code = KRB5_BAD_ENCTYPE;
1248+ goto out;
1249+ }
1250+
1251+ /* allocate memory for output key */
1252+ if ((out->contents = malloc(keylength)) == NULL) {
1253+ code = ENOMEM;
1254+ goto out;
1255+ }
1256+ out->length = keylength;
1257+ out->enctype = in->enctype;
1258+
1259+ datain.data = (char *) constant_data;
1260+ datain.length = K5CLENGTH;
1261+
1262+ datain.data[0] = (usage>>24)&0xff;
1263+ datain.data[1] = (usage>>16)&0xff;
1264+ datain.data[2] = (usage>>8)&0xff;
1265+ datain.data[3] = usage&0xff;
1266+
1267+ datain.data[4] = (char) extra;
1268+
1269+ if ((code = krb5_derive_key(enc, in, out, &datain))) {
1270+ free(out->contents);
1271+ out->contents = NULL;
1272+ }
1273+
1274+ out:
1275+ if (code)
1276+ printerr(0, "ERROR: derive_key returning error %d (%s)\n",
1277+ code, error_message(code));
1278+ return (code);
1279+}
1280+
1281+/*
1282 * We really shouldn't know about glue-layer context structure, but
1283 * we need to get at the real krb5 context pointer. This should be
1284 * removed as soon as we say there is no support for MIT Kerberos
1285@@ -154,48 +272,124 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1286 {
1287 krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
1288 char *p, *end;
1289- static int constant_one = 1;
1290 static int constant_zero = 0;
1291+ static int constant_one = 1;
1292+ static int constant_two = 2;
1293 uint32_t word_seq_send;
1294+ u_int64_t seq_send_64bit;
1295+ uint32_t v2_flags = 0;
1296+ krb5_keyblock derived_key;
1297+ uint32_t numkeys;
1298
1299 if (!(buf->value = calloc(1, MAX_CTX_LEN)))
1300 goto out_err;
1301 p = buf->value;
1302 end = buf->value + MAX_CTX_LEN;
1303
1304- if (kctx->initiate) {
1305- if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1306- }
1307- else {
1308- if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1309- }
1310- if (kctx->seed_init) {
1311- if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1312- }
1313- else {
1314- if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1315- }
1316- if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
71f23813
JR
1317- goto out_err;
1318- if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
1319- if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
1320- if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1321- word_seq_send = kctx->seq_send;
1322- if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
1323- if (write_oid(&p, end, kctx->mech_used)) goto out_err;
97cc26d8
JB
1324+ switch (kctx->sealalg) {
1325+ case SEAL_ALG_DES:
1326+ /* Old format of context to the kernel */
1327+ if (kctx->initiate) {
1328+ if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1329+ }
1330+ else {
1331+ if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1332+ }
1333+ if (kctx->seed_init) {
1334+ if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1335+ }
1336+ else {
1337+ if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1338+ }
1339+ if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
1340+ goto out_err;
1341+ if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
1342+ if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
1343+ if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1344+ word_seq_send = kctx->seq_send;
1345+ if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
1346+ if (write_oid(&p, end, kctx->mech_used)) goto out_err;
1347+
1348+ printerr(2, "serialize_krb5_ctx: serializing keys with "
1349+ "enctype %d and length %d\n",
1350+ kctx->enc->enctype, kctx->enc->length);
1351+
1352+ if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1353+ if (write_keyblock(&p, end, kctx->seq)) goto out_err;
1354+ break;
1355+ case SEAL_ALG_MICROSOFT_RC4:
1356+ case SEAL_ALG_DES3KD:
1357+ /* New format of context to the kernel */
1358+ /* s32 endtime;
1359+ * u32 flags;
1360+ * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
1361+ * #define KRB5_CTX_FLAG_CFX 0x00000002
1362+ * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
1363+ * u64 seq_send;
1364+ * u32 enctype;
1365+ * u32 size_of_each_key; ( size in bytes )
1366+ * u32 number_of_keys; ( N (assumed to be 3 for now) )
1367+ * keydata-1; ( Ke (Kenc for DES3) )
1368+ * keydata-2; ( Ki (Kseq for DES3) )
1369+ * keydata-3; ( Kc (derived checksum key) )
1370+ */
1371+ if (kctx->initiate) {
1372+ if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1373+ }
1374+ else {
1375+ if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1376+ }
1377+ if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1378+
1379+ /* Only applicable flag for this is initiator */
1380+ if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
1381+ if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
1382+
1383+ seq_send_64bit = kctx->seq_send;
1384+ if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
71f23813
JR
1385
1386- printerr(2, "serialize_krb5_ctx: serializing keys with "
1387- "enctype %d and length %d\n",
1388- kctx->enc->enctype, kctx->enc->length);
97cc26d8
JB
1389+ if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
1390+ if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
1391+ numkeys = 3;
1392+ if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
1393+ printerr(2, "serialize_krb5_ctx: serializing %d keys with "
1394+ "enctype %d and size %d\n",
1395+ numkeys, kctx->enc->enctype, kctx->enc->length);
71f23813
JR
1396
1397- if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1398- if (write_keyblock(&p, end, kctx->seq)) goto out_err;
97cc26d8
JB
1399+ /* Ke */
1400+ if (write_bytes(&p, end, kctx->enc->contents,
1401+ kctx->enc->length))
1402+ goto out_err;
1403+
1404+ /* Ki */
1405+ if (write_bytes(&p, end, kctx->enc->contents,
1406+ kctx->enc->length))
1407+ goto out_err;
1408+
1409+ /* Kc */
1410+ if (derive_key(kctx->seq, &derived_key,
1411+ KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1412+ goto out_err;
1413+ if (write_bytes(&p, end, derived_key.contents,
1414+ derived_key.length))
1415+ goto out_err;
1416+ free(derived_key.contents);
1417+ break;
1418+ default:
1419+ printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
1420+ "algorithm %d\n", kctx->sealalg);
71f23813 1421+ goto out_err;
97cc26d8
JB
1422+ }
1423
1424 buf->length = p - (char *)buf->value;
1425 return 0;
1426+
1427 out_err:
1428 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
1429- if (buf->value) free(buf->value);
1430+ if (buf->value) {
1431+ free(buf->value);
1432+ }
1433+ buf->value = NULL;
1434 buf->length = 0;
1435 return -1;
1436 }
This page took 0.212636 seconds and 4 git commands to generate.