1 Add secinfo processing.
3 From: Fred Isaman <iisaman@citi.umich.edu>
5 Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
7 Add secinfo processing.
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(-)
16 Try to use kernel function to determine supported Kerberos enctypes.
18 From: Kevin Coffman <kwc@citi.umich.edu>
20 Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
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
29 utils/gssd/krb5_util.c | 228 +++++++++++++++++++++++++++++++++++++-----------
30 utils/gssd/krb5_util.h | 2
31 3 files changed, 182 insertions(+), 50 deletions(-)
33 Add EXPERIMENTAL support for non-DES encryption types.
35 From: Kevin Coffman <kwc@citi.umich.edu>
37 Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
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.)
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(-)
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"
57 +#define SECFLAVOR_COUNT 7
58 +extern char *secflavor_name[SECFLAVOR_COUNT];
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 {
67 + int e_secinfo_order[SECFLAVOR_COUNT+1];
68 + int e_secinfo_flags[SECFLAVOR_COUNT];
72 @@ -96,6 +101,7 @@ struct rmtabent {
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);
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;
103 @@ -182,6 +187,19 @@ getexportent(int fromkernel, int fromexp
107 +secinfo_show(FILE *fp, struct exportent *ep)
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]);
115 + fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw");
120 putexportent(struct exportent *ep)
123 @@ -199,7 +217,6 @@ putexportent(struct exportent *ep)
124 fprintf(fp, "%c", esc[i]);
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)?
131 @@ -276,7 +293,9 @@ #endif
133 fprintf(fp, "%d,", id[i]);
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");
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;
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;
155 + unsigned int active = 0;
156 + int secmask = NFSEXP_READONLY; /* options that can vary per flavor */
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
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);
181 xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
182 flname, flline, opt);
183 @@ -533,6 +560,12 @@ #endif
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);
200 +char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
210 +secinfo_addflavor(int bit, struct exportent *ep)
213 + for (p=ep->e_secinfo_order; *p>=0; p++) {
219 + ep->e_secinfo_flags[bit] = 0;
223 +secinfo_nameindex(char *name)
226 + for (i=0; i<SECFLAVOR_COUNT; i++) {
227 + if (strcmp(secflavor_name[i], name) == 0)
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.
238 +parse_flavors(char *str, struct exportent *ep)
240 + unsigned int out=0;
244 + while ( (flavor=strsep(&str, ":")) ) {
245 + bit = secinfo_nameindex(flavor);
247 + xlog(L_ERROR, "unknown flavor %s\n", flavor);
251 + secinfo_addflavor(bit, ep);
256 +/* Determine a default security flavor based on ep->e_hostname. */
258 +secinfo_default(struct exportent *ep)
261 + if (strncmp(ep->e_hostname, "gss/", 4) == 0) {
262 + i = secinfo_nameindex(ep->e_hostname + 4);
264 + xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname);
266 + /* Default to auth_sys */
268 + i = secinfo_nameindex("sys");
269 + secinfo_addflavor(i, ep);
273 +/* Sets the bits in @mask for the appropriate security flavor flags. */
275 +setflags(int mask, unsigned int *ap, struct exportent *ep)
277 + int active, flavor=0;
279 + *ap = secinfo_default(ep);
283 + ep->e_secinfo_flags[flavor] |= mask;
289 +/* Clears the bits in @mask for the appropriate security flavor flags. */
291 +clearflags(int mask, unsigned int *ap, struct exportent *ep)
293 + int active, flavor=0;
295 + *ap = secinfo_default(ep);
299 + ep->e_secinfo_flags[flavor] &= ~mask;
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)
313 if (ep->e_flags & NFSEXP_READONLY)
314 c = dumpopt(c, "ro");
316 c = dumpopt(c, "rw");
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
325 + secinfo_show(stdout, ep);
326 printf("%c\n", (c != '(')? ')' : ' ');
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);
337 +static void write_secinfo(FILE *f, struct exportent *ep)
340 + qword_print(f, "secinfo");
341 + for (p=ep->e_secinfo_order; *p>=0; p++)
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]);
350 static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
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);
357 + write_secinfo(f, exp);
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();
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
380 #include <sys/param.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>
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;
398 +/* Encryption types supported by the kernel rpcsec_gss code */
399 +int num_krb5_enctypes = 0;
400 +krb5_enctype *krb5_enctypes = NULL;
402 /*==========================*/
403 /*=== Internal routines ===*/
404 /*==========================*/
405 @@ -256,56 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
409 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
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.
415 - * XXX Should call some function to determine the enctypes supported
416 - * by the kernel. (Only need to do that once!)
419 - * 0 => all went well
420 - * -1 => there was an error
424 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
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]);
432 - /* We only care about getting a krb5 cred */
433 - desired_mechs.count = 1;
434 - desired_mechs.elements = &krb5oid;
436 - maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
437 - &desired_mechs, GSS_C_INITIATE,
438 - &credh, NULL, NULL);
440 - if (maj_stat != GSS_S_COMPLETE) {
441 - pgsserr("gss_acquire_cred",
442 - maj_stat, min_stat, &krb5oid);
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);
457 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
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
467 + * Parse the supported encryption type information
470 +parse_enctypes(char *enctypes)
473 + char *curr, *comma;
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;
483 + /* count the number of commas */
484 + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
485 + comma = strchr(curr, ',');
491 + /* If no more commas and we're not at the end, there's one more value */
495 + /* Empty string, return an error */
499 + /* Allocate space for enctypes array */
500 + if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
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, ',');
512 + num_krb5_enctypes = n;
516 /*==========================*/
517 /*=== External routines ===*/
518 /*==========================*/
519 @@ -860,3 +866,125 @@ gssd_destroy_krb5_machine_creds(void)
520 krb5_free_context(context);
523 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
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.
530 + * 0 => all went well
531 + * -1 => there was an error
535 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
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]);
543 + /* We only care about getting a krb5 cred */
544 + desired_mechs.count = 1;
545 + desired_mechs.elements = &krb5oid;
547 + maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
548 + &desired_mechs, GSS_C_INITIATE,
549 + &credh, NULL, NULL);
551 + if (maj_stat != GSS_S_COMPLETE) {
552 + pgsserr("gss_acquire_cred",
553 + maj_stat, min_stat, &krb5oid);
558 + * If we failed for any reason to produce global
559 + * list of supported enctypes, use local default here.
561 + if (krb5_enctypes == NULL)
562 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
563 + &krb5oid, num_enctypes, &enctypes);
565 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
566 + &krb5oid, num_krb5_enctypes,
568 + if (maj_stat != GSS_S_COMPLETE) {
569 + pgsserr("gss_set_allowable_enctypes",
570 + maj_stat, min_stat, &krb5oid);
577 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
580 + * Obtain supported enctypes from kernel.
581 + * Set defaults if info is not available.
584 +gssd_obtain_kernel_krb5_info(void)
586 + char enctype_file_name[128];
588 + char enctypes[128];
591 + int use_default_enctypes = 0;
592 + int nbytes, numfields;
593 + char default_enctypes[] = "1,3,2";
596 + snprintf(enctype_file_name, sizeof(enctype_file_name),
597 + "%s/%s", pipefs_dir, "krb5_info");
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;
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;
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;
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);
635 + if (use_default_enctypes)
636 + strcpy(enctypes, default_enctypes);
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)" : "",
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);
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
664 - Copyright (c) 2004 The Regents of the University of Michigan.
665 + Copyright (c) 2004-2006 The Regents of the University of Michigan.
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
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
678 int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
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
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.
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;
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);
711 /* derive the encryption key and copy it into buffer */
712 @@ -152,15 +151,361 @@ out_err:
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 */
723 +#define KG_USAGE_SEAL 22
724 +#define KG_USAGE_SIGN 23
725 +#define KG_USAGE_SEQ 24
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
733 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
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
742 +#define KEY_USAGE_SEED_ENCRYPTION 0xAA
743 +#define KEY_USAGE_SEED_INTEGRITY 0x55
744 +#define KEY_USAGE_SEED_CHECKSUM 0x99
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
752 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
753 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
755 + * We don't have "legal" access to these MIT-only
756 + * structures located in libk5crypto
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();
765 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
767 - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
769 + memset(kout, '\0', sizeof(kout));
771 + kout->enctype = lin->type;
772 + kout->length = lin->length;
773 + kout->contents = lin->data;
775 + kout->keytype = lin->type;
776 + kout->keyvalue.length = lin->length;
777 + kout->keyvalue.data = lin->data;
782 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
784 + memset(lout, '\0', sizeof(lout));
786 + lout->type = kin->enctype;
787 + lout->length = kin->length;
788 + lout->data = kin->contents;
790 + lout->type = kin->keytype;
791 + lout->length = kin->keyvalue.length;
792 + memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
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 */
801 + * Function to derive a new key from a given key and given constant data.
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)
807 + krb5_error_code code;
808 + unsigned char constant_data[K5CLENGTH];
812 + krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
814 + krb5_context kcontext;
815 + krb5_keyblock *outkey;
819 + * XXX Hack alert. We don't have "legal" access to these
820 + * values and structures located in libk5crypto
822 + switch (in->type) {
823 + case ENCTYPE_DES3_CBC_SHA1:
825 + case ENCTYPE_DES3_CBC_RAW:
829 + enc = &krb5int_enc_des3;
832 + case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
835 + enc = &krb5int_enc_aes128;
838 + case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
841 + enc = &krb5int_enc_aes256;
845 + code = KRB5_BAD_ENCTYPE;
849 + /* allocate memory for output key */
850 + if ((out->data = malloc(keylength)) == NULL) {
854 + out->length = keylength;
855 + out->type = in->type;
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);
861 + datain.data = (char *) constant_data;
862 + datain.length = K5CLENGTH;
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;
869 + ((char *)(datain.data))[4] = (char) extra;
872 + code = krb5_derive_key(enc, &kin, &kout, &datain);
874 + if ((code = krb5_init_context(&kcontext))) {
876 + code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
884 + key_krb5_to_lucid(&kout, out);
886 + key_krb5_to_lucid(outkey, out);
887 + krb5_free_keyblock(kcontext, outkey);
888 + krb5_free_context(kcontext);
893 + printerr(0, "ERROR: %s: returning error %d (%s)\n",
894 + __FUNCTION__, code, error_message(code));
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.
903 + * The new format is:
905 + * u32 initiate; ( whether we are the initiator or not )
908 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
909 + * #define KRB5_CTX_FLAG_CFX 0x00000002
910 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
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 )
921 +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
922 + gss_buffer_desc *buf)
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;
933 + memset(&enc_key, 0, sizeof(enc_key));
934 + memset(&fakeoid, 0, sizeof(fakeoid));
936 + if (!(buf->value = calloc(1, MAX_CTX_LEN)))
939 + end = buf->value + MAX_CTX_LEN;
942 + if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
943 + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
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;
952 + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
954 + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
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;
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.
966 + if (enctype == ENCTYPE_DES3_CBC_SHA1) {
967 + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
968 + __FUNCTION__, enctype, 6);
973 + keysize = lctx->rfc1964_kd.ctx_key.length;
974 + numkeys = 3; /* XXX is always gonna be three? */
976 + if (lctx->cfx_kd.have_acceptor_subkey) {
977 + enctype = lctx->cfx_kd.acceptor_subkey.type;
978 + keysize = lctx->cfx_kd.acceptor_subkey.length;
980 + enctype = lctx->cfx_kd.ctx_key.type;
981 + keysize = lctx->cfx_kd.ctx_key.length;
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;
991 + if (lctx->protocol == 0) {
992 + /* derive and send down: Ke, Ki, and Kc */
994 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
995 + lctx->rfc1964_kd.ctx_key.length))
999 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
1000 + lctx->rfc1964_kd.ctx_key.length))
1004 + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
1006 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1008 + if (write_bytes(&p, end, derived_key.data,
1009 + derived_key.length))
1011 + free(derived_key.data);
1013 + gss_krb5_lucid_key_t *keyptr;
1014 + uint32_t sign_usage, seal_usage;
1016 + if (lctx->cfx_kd.have_acceptor_subkey)
1017 + keyptr = &lctx->cfx_kd.acceptor_subkey;
1019 + keyptr = &lctx->cfx_kd.ctx_key;
1021 + if (lctx->initiate == 1) {
1022 + sign_usage = KG_USAGE_INITIATOR_SIGN;
1023 + seal_usage = KG_USAGE_INITIATOR_SEAL;
1025 + sign_usage = KG_USAGE_ACCEPTOR_SIGN;
1026 + seal_usage = KG_USAGE_ACCEPTOR_SEAL;
1029 + /* derive and send down: Ke, Ki, and Kc */
1032 + if (derive_key_lucid(keyptr, &derived_key,
1033 + seal_usage, KEY_USAGE_SEED_ENCRYPTION))
1035 + if (write_bytes(&p, end, derived_key.data,
1036 + derived_key.length))
1038 + free(derived_key.data);
1041 + if (derive_key_lucid(keyptr, &derived_key,
1042 + seal_usage, KEY_USAGE_SEED_INTEGRITY))
1044 + if (write_bytes(&p, end, derived_key.data,
1045 + derived_key.length))
1047 + free(derived_key.data);
1050 + if (derive_key_lucid(keyptr, &derived_key,
1051 + sign_usage, KEY_USAGE_SEED_CHECKSUM))
1053 + if (write_bytes(&p, end, derived_key.data,
1054 + derived_key.length))
1056 + free(derived_key.data);
1059 + buf->length = p - (char *)buf->value;
1063 + printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
1067 + buf->value = NULL;
1070 + if (enc_key.data) {
1071 + free(enc_key.data);
1072 + enc_key.data = NULL;
1077 serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
1079 @@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1080 gss_krb5_lucid_context_v1_t *lctx = 0;
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,
1087 if (maj_stat != GSS_S_COMPLETE) {
1088 @@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1092 - /* Now lctx points to a lucid context that we can send down to kernel */
1093 - if (lctx->protocol == 0)
1095 + * Now lctx points to a lucid context that we can send down to kernel
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.
1104 + if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
1105 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
1107 - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
1108 + retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
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
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);
1123 @@ -217,4 +571,7 @@ out_err:
1124 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
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
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.
1141 Redistribution and use in source and binary forms, with or without
1142 @@ -36,6 +36,7 @@ #ifdef HAVE_KRB5
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 :-/
1155 - * XXX Does this match the Heimdal definition? */
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
1164 + * XXX Hack alert! XXX Do NOT submit upstream!
1165 + * XXX Hack alert! XXX Do NOT submit upstream!
1167 + * We shouldn't be using these definitions
1169 + * XXX Hack alert! XXX Do NOT submit upstream!
1170 + * XXX Hack alert! XXX Do NOT submit upstream!
1173 +#define KG_USAGE_SEAL 22
1174 +#define KG_USAGE_SIGN 23
1175 +#define KG_USAGE_SEQ 24
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
1183 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
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
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
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();
1205 + * XXX Hack alert! XXX Do NOT submit upstream!
1206 + * XXX Hack alert! XXX Do NOT submit upstream!
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
1213 + * XXX Hack alert! XXX Do NOT submit upstream!
1214 + * XXX Hack alert! XXX Do NOT submit upstream!
1217 + * Function to derive a new key from a given key and given constant data.
1219 +static krb5_error_code
1220 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
1222 + krb5_error_code code;
1223 + unsigned char constant_data[K5CLENGTH];
1228 + switch (in->enctype) {
1229 +#ifdef ENCTYPE_DES3_CBC_RAW
1230 + case ENCTYPE_DES3_CBC_RAW:
1232 +/* Extra hack, the structure was renamed as rc4 was added... */
1233 +#if defined(ENCTYPE_ARCFOUR_HMAC)
1234 + enc = &krb5int_enc_des3;
1236 + enc = &krb5_enc_des3;
1240 +#ifdef ENCTYPE_ARCFOUR_HMAC
1241 + case ENCTYPE_ARCFOUR_HMAC:
1243 + enc = &krb5int_enc_arcfour;
1247 + code = KRB5_BAD_ENCTYPE;
1251 + /* allocate memory for output key */
1252 + if ((out->contents = malloc(keylength)) == NULL) {
1256 + out->length = keylength;
1257 + out->enctype = in->enctype;
1259 + datain.data = (char *) constant_data;
1260 + datain.length = K5CLENGTH;
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;
1267 + datain.data[4] = (char) extra;
1269 + if ((code = krb5_derive_key(enc, in, out, &datain))) {
1270 + free(out->contents);
1271 + out->contents = NULL;
1276 + printerr(0, "ERROR: derive_key returning error %d (%s)\n",
1277 + code, error_message(code));
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
1287 krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
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;
1299 if (!(buf->value = calloc(1, MAX_CTX_LEN)))
1302 end = buf->value + MAX_CTX_LEN;
1304 - if (kctx->initiate) {
1305 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1308 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1310 - if (kctx->seed_init) {
1311 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1314 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1316 - if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
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;
1331 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1333 + if (kctx->seed_init) {
1334 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1337 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1339 + if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
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;
1348 + printerr(2, "serialize_krb5_ctx: serializing keys with "
1349 + "enctype %d and length %d\n",
1350 + kctx->enc->enctype, kctx->enc->length);
1352 + if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1353 + if (write_keyblock(&p, end, kctx->seq)) goto out_err;
1355 + case SEAL_ALG_MICROSOFT_RC4:
1356 + case SEAL_ALG_DES3KD:
1357 + /* New format of context to the kernel */
1360 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
1361 + * #define KRB5_CTX_FLAG_CFX 0x00000002
1362 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
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) )
1371 + if (kctx->initiate) {
1372 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1375 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1377 + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
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;
1383 + seq_send_64bit = kctx->seq_send;
1384 + if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
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;
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);
1397 - if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1398 - if (write_keyblock(&p, end, kctx->seq)) goto out_err;
1400 + if (write_bytes(&p, end, kctx->enc->contents,
1401 + kctx->enc->length))
1405 + if (write_bytes(&p, end, kctx->enc->contents,
1406 + kctx->enc->length))
1410 + if (derive_key(kctx->seq, &derived_key,
1411 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1413 + if (write_bytes(&p, end, derived_key.contents,
1414 + derived_key.length))
1416 + free(derived_key.contents);
1419 + printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
1420 + "algorithm %d\n", kctx->sealalg);
1424 buf->length = p - (char *)buf->value;
1428 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
1429 - if (buf->value) free(buf->value);
1433 + buf->value = NULL;