]> git.pld-linux.org Git - packages/nfs-utils.git/blob - nfs-utils-CITI_NFS4.patch
- remove the last remaining redhatism (/bin/bash) along with original author
[packages/nfs-utils.git] / nfs-utils-CITI_NFS4.patch
1 Add secinfo processing.
2
3 From: Fred Isaman <iisaman@citi.umich.edu>
4
5 Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
6
7 Add 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
16 Try to use kernel function to determine supported Kerberos enctypes.
17
18 From: Kevin Coffman <kwc@citi.umich.edu>
19
20 Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
21
22 This patch replaces a hard-coded list with a function to obtain
23 the Kerberos encryption types that the kernel's rpcsec_gss code
24 can support.  Defaults to old behavior if kernel does not supply
25 information.
26 ---
27
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(-)
32
33 Add EXPERIMENTAL support for non-DES encryption types.
34
35 From: Kevin Coffman <kwc@citi.umich.edu>
36
37 Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
38
39 Adds EXPERIMENTAL support for non-DES encryption types.  Sends a new
40 format of context information to the kernel.
41 (Requires kernel support to do anything useful.)
42 ---
43
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(-)
48
49 diff --git a/support/include/nfslib.h b/support/include/nfslib.h
50 index 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
56  
57 +#define SECFLAVOR_COUNT 7
58 +extern char *secflavor_name[SECFLAVOR_COUNT];
59 +
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);
80 diff --git a/support/nfs/exports.c b/support/nfs/exports.c
81 index 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);
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)
95 @@ -102,6 +106,7 @@ getexportent(int fromkernel, int fromexp
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  
103 @@ -182,6 +187,19 @@ getexportent(int fromkernel, int fromexp
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;
123 @@ -199,7 +217,6 @@ putexportent(struct exportent *ep)
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_");
131 @@ -276,7 +293,9 @@ #endif
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
142 @@ -325,6 +344,7 @@ mkexportent(char *hname, char *path, cha
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;
150 @@ -376,6 +396,9 @@ parseopts(char *cp, struct exportent *ep
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;
160 @@ -398,9 +421,9 @@ parseopts(char *cp, struct exportent *ep
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"))
172 @@ -522,6 +545,10 @@ #endif
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);
183 @@ -533,6 +560,12 @@ #endif
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;
196 @@ -663,3 +696,107 @@ syntaxerr(char *msg)
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 +}
304 diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
305 index 22e13a3..30732b8 100644
306 --- a/utils/exportfs/exportfs.c
307 +++ b/utils/exportfs/exportfs.c
308 @@ -376,10 +376,12 @@ dump(int verbose)
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)
321 @@ -433,6 +435,7 @@ #ifdef DEBUG
322                                 break;
323  #endif
324                         }
325 +                       secinfo_show(stdout, ep);
326                         printf("%c\n", (c != '(')? ')' : ' ');
327                 }
328         }
329 diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
330 index 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);
335  }
336  
337 +static void write_secinfo(FILE *f, struct exportent *ep)
338 +{
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]);
347 +       }
348 +}
349 +
350  static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
351  {
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                 }
356  #endif
357 +               write_secinfo(f, exp);
358         }
359         return qword_eol(f);
360  }
361 diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
362 index 08a6c10..44afdd0 100644
363 --- a/utils/gssd/gssd.c
364 +++ b/utils/gssd/gssd.c
365 @@ -162,6 +162,8 @@ #endif
366         /* Process keytab file and get machine credentials */
367         if (root_uses_machine_creds)
368                 gssd_refresh_krb5_machine_creds();
369 +       /* Determine Kerberos information from the kernel */
370 +       gssd_obtain_kernel_krb5_info();
371  
372         gssd_run();
373         printerr(0, "gssd_run returned!\n");
374 diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
375 index 096f6cf..96e91ae 100644
376 --- a/utils/gssd/krb5_util.c
377 +++ b/utils/gssd/krb5_util.c
378 @@ -97,6 +97,7 @@ #endif
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>
386 @@ -105,6 +106,7 @@ #include <stdio.h>
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>
394 @@ -123,6 +125,10 @@ #include "krb5_util.h"
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.
462 @@ -609,6 +565,56 @@ #else
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 +}
645 diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
646 index da04530..2af1a25 100644
647 --- a/utils/gssd/krb5_util.h
648 +++ b/utils/gssd/krb5_util.h
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);
658 diff --git a/utils/gssd/context.h b/utils/gssd/context.h
659 index 67ed3bb..68b0c11 100644
660 --- a/utils/gssd/context.h
661 +++ b/utils/gssd/context.h
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
669 @@ -36,6 +36,10 @@ #include <rpc/rpc.h>
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);
680 diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
681 index 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
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"
692 @@ -113,15 +114,13 @@ #ifdef HAVE_HEIMDAL
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
779 +}
780 +
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 +}
795 +
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);
896  }
897  
898  
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 */
1131 diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
1132 index 94b2266..cd6ab0f 100644
1133 --- a/utils/gssd/context_mit.c
1134 +++ b/utils/gssd/context_mit.c
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
1142 @@ -36,6 +36,7 @@ #ifdef HAVE_KRB5
1143  #include <stdio.h>
1144  #include <syslog.h>
1145  #include <string.h>
1146 +#include <errno.h>
1147  #include <gssapi/gssapi.h>
1148  #include <rpc/rpc.h>
1149  #include <rpc/auth_gss.h>
1150 @@ -50,8 +51,7 @@ #if (KRB5_VERSION > 131)
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)))
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;
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;
1385  
1386 -       printerr(2, "serialize_krb5_ctx: serializing keys with "
1387 -                "enctype %d and length %d\n",
1388 -                kctx->enc->enctype, kctx->enc->length);
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);
1396  
1397 -       if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1398 -       if (write_keyblock(&p, end, kctx->seq)) goto out_err;
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);
1421 +               goto out_err;
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.15061 seconds and 3 git commands to generate.