3 The complete set of CITI nfs-utils patches rolled into one patch.
5 Changes since 1.0.8-rc4-CITI_NFS4_ALL-3:
7 * Update to the final nfs-utils-1.0.8
9 * Check for problems with the gssapi library in gssd and svcgssd
10 early on, so we can give a good error message and bail out.
12 * Add temporary patch to svcgssd to use default values when the
13 mapping of the gss principal to uid/gid fails. This may need
14 to somehow coordinate with the anonuid/anongid values for the
20 nfs-utils-1.0.8-kwc/utils/gssd/context_mit.c | 507 ++++++++++++++++++++++++--
21 nfs-utils-1.0.8-kwc/utils/gssd/gss_util.c | 25 +
22 nfs-utils-1.0.8-kwc/utils/gssd/gss_util.h | 1
23 nfs-utils-1.0.8-kwc/utils/gssd/gssd.c | 5
24 nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.c | 221 +++++++++--
25 nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.h | 2
26 nfs-utils-1.0.8-kwc/utils/gssd/svcgssd.c | 5
27 nfs-utils-1.0.8-kwc/utils/gssd/svcgssd_proc.c | 17
28 nfs-utils-1.0.8-kwc/utils/gssd/write_bytes.h | 13
29 9 files changed, 714 insertions(+), 82 deletions(-)
31 diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c
32 --- nfs-utils-1.0.8/utils/gssd/gssd.c~CITI_NFS4_ALL 2006-04-20 12:41:15.668400000 -0400
33 +++ nfs-utils-1.0.8-kwc/utils/gssd/gssd.c 2006-04-20 12:41:16.486965000 -0400
34 @@ -145,6 +145,9 @@ main(int argc, char *argv[])
35 "support setting debug level\n");
38 + if (gssd_check_mechs() != 0)
39 + errx(1, "Problem with gssapi library");
41 if (!fg && daemon(0, 0) < 0)
44 @@ -154,6 +157,8 @@ main(int argc, char *argv[])
46 /* Process keytab file and get machine credentials */
47 gssd_refresh_krb5_machine_creds();
48 + /* Determine Kerberos information from the kernel */
49 + gssd_obtain_kernel_krb5_info();
52 printerr(0, "gssd_run returned!\n");
53 diff -puN utils/gssd/gss_util.c~CITI_NFS4_ALL utils/gssd/gss_util.c
54 --- nfs-utils-1.0.8/utils/gssd/gss_util.c~CITI_NFS4_ALL 2006-04-20 12:41:15.770298000 -0400
55 +++ nfs-utils-1.0.8-kwc/utils/gssd/gss_util.c 2006-04-20 12:41:16.001067000 -0400
56 @@ -224,3 +224,28 @@ gssd_acquire_cred(char *server_name)
58 return (maj_stat == GSS_S_COMPLETE);
61 +int gssd_check_mechs(void)
63 + u_int32_t maj_stat, min_stat;
64 + gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
67 + maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs);
68 + if (maj_stat != GSS_S_COMPLETE) {
69 + printerr(0, "Unable to obtain list of supported mechanisms. "
70 + "Check that gss library is properly configured.\n");
73 + if (supported_mechs == GSS_C_NO_OID_SET ||
74 + supported_mechs->count == 0) {
75 + printerr(0, "Unable to obtain list of supported mechanisms. "
76 + "Check that gss library is properly configured.\n");
79 + maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
85 diff -puN utils/gssd/gss_util.h~CITI_NFS4_ALL utils/gssd/gss_util.h
86 --- nfs-utils-1.0.8/utils/gssd/gss_util.h~CITI_NFS4_ALL 2006-04-20 12:41:15.865203000 -0400
87 +++ nfs-utils-1.0.8-kwc/utils/gssd/gss_util.h 2006-04-20 12:41:16.011057000 -0400
88 @@ -40,5 +40,6 @@ extern gss_cred_id_t gssd_creds;
89 int gssd_acquire_cred(char *server_name);
90 void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
92 +int gssd_check_mechs(void);
94 #endif /* _GSS_UTIL_H_ */
95 diff -puN utils/gssd/svcgssd.c~CITI_NFS4_ALL utils/gssd/svcgssd.c
96 --- nfs-utils-1.0.8/utils/gssd/svcgssd.c~CITI_NFS4_ALL 2006-04-20 12:41:15.961107000 -0400
97 +++ nfs-utils-1.0.8-kwc/utils/gssd/svcgssd.c 2006-04-20 12:41:16.021047000 -0400
98 @@ -204,6 +204,11 @@ main(int argc, char *argv[])
99 "support setting debug level\n");
102 + if (gssd_check_mechs() != 0) {
103 + printerr(0, "ERROR: Problem with gssapi library\n");
110 diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c
111 --- nfs-utils-1.0.8/utils/gssd/krb5_util.c~CITI_NFS4_ALL 2006-04-20 12:41:16.230965000 -0400
112 +++ nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.c 2006-04-20 12:41:16.503965000 -0400
115 #include <sys/param.h>
117 +#include <sys/types.h>
118 #include <sys/stat.h>
119 #include <sys/socket.h>
120 #include <arpa/inet.h>
128 #include <gssapi/gssapi.h>
130 /* Global list of principals/cache file names for machine credentials */
131 struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
133 +/* Encryption types supported by the kernel rpcsec_gss code */
134 +int num_krb5_enctypes = 0;
135 +krb5_enctype *krb5_enctypes = NULL;
137 /*==========================*/
138 /*=== Internal routines ===*/
139 /*==========================*/
140 @@ -261,51 +267,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
144 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
146 - * this routine obtains a credentials handle via gss_acquire_cred()
147 - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
148 - * types negotiated.
150 - * XXX Should call some function to determine the enctypes supported
151 - * by the kernel. (Only need to do that once!)
154 - * 0 => all went well
155 - * -1 => there was an error
159 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
161 - u_int maj_stat, min_stat;
162 - gss_cred_id_t credh;
163 - krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
164 - int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
166 - maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
167 - GSS_C_NULL_OID_SET, GSS_C_INITIATE,
168 - &credh, NULL, NULL);
170 - if (maj_stat != GSS_S_COMPLETE) {
171 - pgsserr("gss_acquire_cred",
172 - maj_stat, min_stat, &krb5oid);
176 - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
177 - num_enctypes, &enctypes);
178 - if (maj_stat != GSS_S_COMPLETE) {
179 - pgsserr("gss_set_allowable_enctypes",
180 - maj_stat, min_stat, &krb5oid);
187 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
190 * Obtain credentials via a key in the keytab given
191 * a keytab handle and a gssd_k5_kt_princ structure.
192 @@ -603,6 +564,56 @@ gssd_set_krb5_ccache_name(char *ccname)
197 + * Parse the supported encryption type information
200 +parse_enctypes(char *enctypes)
203 + char *curr, *comma;
206 + /* Just in case this ever gets called more than once */
207 + if (krb5_enctypes != NULL) {
208 + free(krb5_enctypes);
209 + krb5_enctypes = NULL;
210 + num_krb5_enctypes = 0;
213 + /* count the number of commas */
214 + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
215 + comma = strchr(curr, ',');
221 + /* If no more commas and we're not at the end, there's one more value */
225 + /* Empty string, return an error */
229 + /* Allocate space for enctypes array */
230 + if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
234 + /* Now parse each value into the array */
235 + for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
236 + krb5_enctypes[i++] = atoi(curr);
237 + comma = strchr(curr, ',');
242 + num_krb5_enctypes = n;
246 /*==========================*/
247 /*=== External routines ===*/
248 /*==========================*/
249 @@ -854,3 +865,123 @@ gssd_destroy_krb5_machine_creds(void)
250 krb5_free_context(context);
253 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
255 + * this routine obtains a credentials handle via gss_acquire_cred()
256 + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
257 + * types negotiated.
260 + * 0 => all went well
261 + * -1 => there was an error
265 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
267 + u_int maj_stat, min_stat;
268 + gss_cred_id_t credh;
269 + gss_OID_set_desc desired_mechs;
270 + krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
271 + int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
273 + /* We only care about getting a krb5 cred */
274 + desired_mechs.count = 1;
275 + desired_mechs.elements = &krb5oid;
277 + maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
278 + &desired_mechs, GSS_C_INITIATE,
279 + &credh, NULL, NULL);
281 + if (maj_stat != GSS_S_COMPLETE) {
282 + pgsserr("gss_acquire_cred",
283 + maj_stat, min_stat, &krb5oid);
288 + * If we failed for any reason to produce global
289 + * list of supported enctypes, use local default here.
291 + if (krb5_enctypes == NULL)
292 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
293 + &krb5oid, num_enctypes, &enctypes);
295 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
296 + &krb5oid, num_krb5_enctypes,
298 + if (maj_stat != GSS_S_COMPLETE) {
299 + pgsserr("gss_set_allowable_enctypes",
300 + maj_stat, min_stat, &krb5oid);
307 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
310 + * Obtain supported enctypes from kernel.
311 + * Set defaults if info is not available.
314 +gssd_obtain_kernel_krb5_info(void)
316 + char enctype_file_name[128];
318 + char enctypes[128];
319 + char extrainfo[1024];
321 + int use_default_enctypes = 0;
322 + int nbytes, numfields;
323 + char default_enctypes[] = "1,3,2";
326 + snprintf(enctype_file_name, sizeof(enctype_file_name),
327 + "%s/%s", pipefsdir, "krb5_info");
329 + if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
330 + printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
331 + "Unable to open '%s'. Unable to determine "
332 + "Kerberos encryption types supported by the "
333 + "kernel; using defaults (%s).\n",
334 + enctype_file_name, default_enctypes);
335 + use_default_enctypes = 1;
338 + if ((nbytes = read(fd, buf, sizeof(buf))) == -1) {
339 + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
340 + "Error reading Kerberos encryption type "
341 + "information file '%s'; using defaults (%s).\n",
342 + enctype_file_name, default_enctypes);
343 + use_default_enctypes = 1;
346 + numfields = sscanf(buf, "enctypes: %s\n%s", enctypes, extrainfo);
347 + if (numfields < 1) {
348 + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
349 + "error parsing Kerberos encryption type "
350 + "information from file '%s'; using defaults (%s).\n",
351 + enctype_file_name, default_enctypes);
352 + use_default_enctypes = 1;
355 + if (numfields > 1) {
356 + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
357 + "Extra information, '%s', from '%s' is ignored\n",
358 + enctype_file_name, extrainfo);
359 + use_default_enctypes = 1;
363 + if (use_default_enctypes)
364 + strcpy(enctypes, default_enctypes);
366 + if ((code = parse_enctypes(enctypes)) != 0) {
367 + printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
368 + "parse_enctypes%s failed with code %d\n",
369 + use_default_enctypes ? " (with default enctypes)" : "",
373 diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h
374 --- nfs-utils-1.0.8/utils/gssd/krb5_util.h~CITI_NFS4_ALL 2006-04-20 12:41:16.461965000 -0400
375 +++ nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.h 2006-04-20 12:41:16.513965000 -0400
376 @@ -22,6 +22,8 @@ int gssd_refresh_krb5_machine_creds(voi
377 void gssd_free_krb5_machine_cred_list(char **list);
378 void gssd_setup_krb5_machine_gss_ccache(char *servername);
379 void gssd_destroy_krb5_machine_creds(void);
380 +void gssd_obtain_kernel_krb5_info(void);
383 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
384 int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
385 diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c
386 --- nfs-utils-1.0.8/utils/gssd/context_mit.c~CITI_NFS4_ALL 2006-04-20 12:41:16.770847000 -0400
387 +++ nfs-utils-1.0.8-kwc/utils/gssd/context_mit.c 2006-04-20 12:41:16.894723000 -0400
395 #include <rpc/auth_gss.h>
401 +#define KG_USAGE_SEAL 22
402 +#define KG_USAGE_SIGN 23
403 +#define KG_USAGE_SEQ 24
406 +#define KG_USAGE_ACCEPTOR_SEAL 22
407 +#define KG_USAGE_ACCEPTOR_SIGN 23
408 +#define KG_USAGE_INITIATOR_SEAL 24
409 +#define KG_USAGE_INITIATOR_SIGN 25
411 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
413 + SEAL_ALG_NONE = 0xffff,
414 + SEAL_ALG_DES = 0x0000,
415 + SEAL_ALG_1 = 0x0001, /* not published */
416 + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
417 + SEAL_ALG_DES3KD = 0x0002
420 +#define KEY_USAGE_SEED_ENCRYPTION 0xAA
421 +#define KEY_USAGE_SEED_INTEGRITY 0x55
422 +#define KEY_USAGE_SEED_CHECKSUM 0x99
425 +/* Flags for version 2 context flags */
426 +#define KRB5_CTX_FLAG_INITIATOR 0x00000001
427 +#define KRB5_CTX_FLAG_CFX 0x00000002
428 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
431 + * XXX Hack alert. We don't have "legal" access to these
432 + * structures located in libk5crypto
434 +extern void krb5int_enc_arcfour;
435 +extern void krb5int_enc_des3;
436 +extern void krb5int_enc_aes128;
437 +extern void krb5int_enc_aes256;
438 +extern int krb5_derive_key();
440 +void *get_enc_provider();
442 /* XXX spkm3 seems to actually want it this big, yipes. */
443 #define MAX_CTX_LEN 4096
447 #ifdef HAVE_LUCID_CONTEXT_SUPPORT
449 /* Don't use the private structure, use the exported lucid structure */
450 @@ -144,6 +189,96 @@ write_lucid_keyblock(char **p, char *end
455 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
457 + memset(kout, '\0', sizeof(kout));
458 + kout->enctype = lin->type;
459 + kout->length = lin->length;
460 + kout->contents = lin->data;
464 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
466 + memset(lout, '\0', sizeof(lout));
467 + lout->type = kin->enctype;
468 + lout->length = kin->length;
469 + lout->data = kin->contents;
473 + * Function to derive a new key from a given key and given constant data.
475 +static krb5_error_code
476 +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
477 + int usage, char extra)
479 + krb5_error_code code;
480 + unsigned char constant_data[K5CLENGTH];
484 + krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
487 + * XXX Hack alert. We don't have "legal" access to these
488 + * values and structures located in libk5crypto
490 + switch (in->type) {
491 + case ENCTYPE_DES3_CBC_RAW:
493 + enc = &krb5int_enc_des3;
495 + case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
497 + enc = &krb5int_enc_aes128;
499 + case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
501 + enc = &krb5int_enc_aes256;
504 + code = KRB5_BAD_ENCTYPE;
508 + /* allocate memory for output key */
509 + if ((out->data = malloc(keylength)) == NULL) {
513 + out->length = keylength;
514 + out->type = in->type;
516 + /* Convert to correct format for call to krb5_derive_key */
517 + key_lucid_to_krb5(in, &kin);
518 + key_lucid_to_krb5(out, &kout);
520 + datain.data = (char *) constant_data;
521 + datain.length = K5CLENGTH;
523 + datain.data[0] = (usage>>24)&0xff;
524 + datain.data[1] = (usage>>16)&0xff;
525 + datain.data[2] = (usage>>8)&0xff;
526 + datain.data[3] = usage&0xff;
528 + datain.data[4] = (char) extra;
530 + if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) {
535 + key_krb5_to_lucid(&kout, out);
539 + printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n",
540 + code, error_message(code));
545 prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
546 gss_buffer_desc *buf)
547 @@ -183,7 +318,7 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc
548 if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
549 word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */
550 if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
551 - if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
552 + if (write_oid(&p, end, &krb5oid)) goto out_err;
554 printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
555 "enctype %d and length %d\n",
556 @@ -212,17 +347,180 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc
559 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
560 - if (buf->value) free(buf->value);
566 - if (enc_key.data) free(enc_key.data);
567 + if (enc_key.data) {
568 + free(enc_key.data);
569 + enc_key.data = NULL;
575 + * Prepare a new-style buffer to send to the kernel for newer encryption
576 + * types -- or for DES3.
578 + * The new format is:
580 + * u32 version; This is two (2)
583 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
584 + * #define KRB5_CTX_FLAG_CFX 0x00000002
585 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
587 + * u32 enctype; ( encrption type of keys )
588 + * u32 size_of_each_key; ( size of each key in bytes )
589 + * u32 number_of_keys; ( N -- should always be 3 for now )
590 + * keydata-1; ( Ke )
591 + * keydata-2; ( Ki )
592 + * keydata-3; ( Kc )
596 -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
597 +prepare_krb5_ctx_v2_buffer(gss_krb5_lucid_context_v1_t *lctx,
598 gss_buffer_desc *buf)
600 - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
602 + static uint32_t version = 2;
603 + uint32_t v2_flags = 0;
604 + gss_krb5_lucid_key_t enc_key;
605 + gss_krb5_lucid_key_t derived_key;
606 + gss_buffer_desc fakeoid;
611 + memset(&enc_key, 0, sizeof(enc_key));
612 + memset(&fakeoid, 0, sizeof(fakeoid));
614 + if (!(buf->value = calloc(1, MAX_CTX_LEN)))
617 + end = buf->value + MAX_CTX_LEN;
620 + if (WRITE_BYTES(&p, end , version)) goto out_err;
621 + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
623 + if (lctx->initiate)
624 + v2_flags |= KRB5_CTX_FLAG_INITIATOR;
625 + if (lctx->protocol != 0)
626 + v2_flags |= KRB5_CTX_FLAG_CFX;
627 + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
628 + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
630 + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
632 + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
634 + /* Protocol 0 here implies DES3 or RC4 */
635 + if (lctx->protocol == 0) {
636 + enctype = lctx->rfc1964_kd.ctx_key.type;
637 + keysize = lctx->rfc1964_kd.ctx_key.length;
638 + numkeys = 3; /* XXX is always gonna be three? */
640 + if (lctx->cfx_kd.have_acceptor_subkey) {
641 + enctype = lctx->cfx_kd.acceptor_subkey.type;
642 + keysize = lctx->cfx_kd.acceptor_subkey.length;
644 + enctype = lctx->cfx_kd.ctx_key.type;
645 + keysize = lctx->cfx_kd.ctx_key.length;
649 + printerr(2, "prepare_krb5_ctx_v2_buffer: serializing %d keys with "
650 + "enctype %d and size %d\n", numkeys, enctype, keysize);
651 + if (WRITE_BYTES(&p, end, enctype)) goto out_err;
652 + if (WRITE_BYTES(&p, end, keysize)) goto out_err;
653 + if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
655 + if (lctx->protocol == 0) {
656 + /* derive and send down: Ke, Ki, and Kc */
658 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
659 + lctx->rfc1964_kd.ctx_key.length))
663 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
664 + lctx->rfc1964_kd.ctx_key.length))
668 + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
670 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
672 + if (write_bytes(&p, end, derived_key.data,
673 + derived_key.length))
675 + free(derived_key.data);
677 + gss_krb5_lucid_key_t *keyptr;
678 + uint32_t sign_usage, seal_usage;
680 + if (lctx->cfx_kd.have_acceptor_subkey)
681 + keyptr = &lctx->cfx_kd.acceptor_subkey;
683 + keyptr = &lctx->cfx_kd.ctx_key;
685 + if (lctx->initiate == 1) {
686 + sign_usage = KG_USAGE_INITIATOR_SIGN;
687 + seal_usage = KG_USAGE_INITIATOR_SEAL;
689 + sign_usage = KG_USAGE_ACCEPTOR_SIGN;
690 + seal_usage = KG_USAGE_ACCEPTOR_SEAL;
693 + /* derive and send down: Ke, Ki, and Kc */
696 + if (derive_key_lucid(keyptr, &derived_key,
697 + seal_usage, KEY_USAGE_SEED_ENCRYPTION))
699 + if (write_bytes(&p, end, derived_key.data,
700 + derived_key.length))
702 + free(derived_key.data);
705 + if (derive_key_lucid(keyptr, &derived_key,
706 + seal_usage, KEY_USAGE_SEED_INTEGRITY))
708 + if (write_bytes(&p, end, derived_key.data,
709 + derived_key.length))
711 + free(derived_key.data);
714 + if (derive_key_lucid(keyptr, &derived_key,
715 + sign_usage, KEY_USAGE_SEED_CHECKSUM))
717 + if (write_bytes(&p, end, derived_key.data,
718 + derived_key.length))
720 + free(derived_key.data);
723 + buf->length = p - (char *)buf->value;
727 + printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: "
728 + "failed serializing krb5 context for kernel\n");
734 + if (enc_key.data) {
735 + free(enc_key.data);
736 + enc_key.data = NULL;
741 @@ -258,11 +556,21 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
745 - /* Now lctx points to a lucid context that we can send down to kernel */
746 - if (lctx->protocol == 0)
748 + * Now lctx points to a lucid context that we can send down to kernel
750 + * Note: we send down different information to the kernel depending
751 + * on the protocol version and the enctyption type.
752 + * For protocol version 0 with all enctypes besides DES3, we use
753 + * the original format. For protocol version != 0 or DES3, we
754 + * send down the new style information.
757 + if (lctx->protocol == 0 &&
758 + lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW)
759 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
761 - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
762 + retcode = prepare_krb5_ctx_v2_buffer(lctx, buf);
764 maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
765 if (maj_stat != GSS_S_COMPLETE) {
766 @@ -300,6 +608,66 @@ write_keyblock(char **p, char *end, stru
770 + * Function to derive a new key from a given key and given constant data.
772 +static krb5_error_code
773 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
775 + krb5_error_code code;
776 + unsigned char constant_data[K5CLENGTH];
782 + * XXX Hack alert. We don't have "legal" access to these
783 + * values and structures located in libk5crypto
785 + switch (in->enctype) {
786 + case ENCTYPE_DES3_CBC_RAW:
788 + enc = &krb5int_enc_des3;
790 + case ENCTYPE_ARCFOUR_HMAC:
792 + enc = &krb5int_enc_arcfour;
795 + code = KRB5_BAD_ENCTYPE;
799 + /* allocate memory for output key */
800 + if ((out->contents = malloc(keylength)) == NULL) {
804 + out->length = keylength;
805 + out->enctype = in->enctype;
807 + datain.data = (char *) constant_data;
808 + datain.length = K5CLENGTH;
810 + datain.data[0] = (usage>>24)&0xff;
811 + datain.data[1] = (usage>>16)&0xff;
812 + datain.data[2] = (usage>>8)&0xff;
813 + datain.data[3] = usage&0xff;
815 + datain.data[4] = (char) extra;
817 + if ((code = krb5_derive_key(enc, in, out, &datain))) {
818 + free(out->contents);
819 + out->contents = NULL;
824 + printerr(0, "ERROR: derive_key returning error %d (%s)\n",
825 + code, error_message(code));
830 * We really shouldn't know about glue-layer context structure, but
831 * we need to get at the real krb5 context pointer. This should be
832 * removed as soon as we say there is no support for MIT Kerberos
833 @@ -315,45 +683,114 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
835 krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
837 - static int constant_one = 1;
838 static int constant_zero = 0;
839 + static int constant_one = 1;
840 + static int constant_two = 2;
841 uint32_t word_seq_send;
842 + u_int64_t seq_send_64bit;
843 + uint32_t v2_flags = 0;
844 + krb5_keyblock derived_key;
847 if (!(buf->value = calloc(1, MAX_CTX_LEN)))
850 end = buf->value + MAX_CTX_LEN;
852 - if (kctx->initiate) {
853 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
856 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
858 - if (kctx->seed_init) {
859 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
862 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
864 - if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
866 - if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
867 - if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
868 - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
869 - word_seq_send = kctx->seq_send;
870 - if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
871 - if (write_buffer(&p, end, kctx->mech_used)) goto out_err;
873 - printerr(2, "serialize_krb5_ctx: serializing keys with "
874 - "enctype %d and length %d\n",
875 - kctx->enc->enctype, kctx->enc->length);
876 + switch (kctx->sealalg) {
878 + /* Versions 0 and 1 */
879 + if (kctx->initiate) {
880 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
883 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
885 + if (kctx->seed_init) {
886 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
889 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
891 + if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
893 + if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
894 + if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
895 + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
896 + word_seq_send = kctx->seq_send;
897 + if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
898 + if (write_buffer(&p, end, kctx->mech_used)) goto out_err;
900 + printerr(2, "serialize_krb5_ctx: serializing keys with "
901 + "enctype %d and length %d\n",
902 + kctx->enc->enctype, kctx->enc->length);
904 - if (write_keyblock(&p, end, kctx->enc)) goto out_err;
905 - if (write_keyblock(&p, end, kctx->seq)) goto out_err;
906 + if (write_keyblock(&p, end, kctx->enc)) goto out_err;
907 + if (write_keyblock(&p, end, kctx->seq)) goto out_err;
909 + case SEAL_ALG_MICROSOFT_RC4:
910 + case SEAL_ALG_DES3KD:
911 + /* u32 version; ( 2 )
914 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
915 + * #define KRB5_CTX_FLAG_CFX 0x00000002
916 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
919 + * u32 size_of_each_key; ( size in bytes )
920 + * u32 number_of_keys; ( N (assumed to be 3 for now) )
921 + * keydata-1; ( Ke (Kenc for DES3) )
922 + * keydata-2; ( Ki (Kseq for DES3) )
923 + * keydata-3; ( Kc (derived checksum key) )
926 + if (WRITE_BYTES(&p, end , constant_two)) goto out_err;
927 + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
929 + /* Only applicable flag for is initiator */
930 + if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
931 + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
933 + seq_send_64bit = kctx->seq_send;
934 + if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
936 + if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
937 + if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
939 + if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
940 + printerr(2, "serialize_krb5_ctx: serializing %d keys with "
941 + "enctype %d and size %d\n",
942 + numkeys, kctx->enc->enctype, kctx->enc->length);
945 + if (write_bytes(&p, end, kctx->enc->contents,
946 + kctx->enc->length))
950 + if (write_bytes(&p, end, kctx->enc->contents,
951 + kctx->enc->length))
955 + if (derive_key(kctx->seq, &derived_key,
956 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
958 + if (write_bytes(&p, end, derived_key.contents,
959 + derived_key.length))
961 + free(derived_key.contents);
964 + printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
965 + "algorithm %d\n", kctx->sealalg);
969 buf->length = p - (char *)buf->value;
973 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
974 if (buf->value) free(buf->value);
975 diff -puN utils/gssd/write_bytes.h~CITI_NFS4_ALL utils/gssd/write_bytes.h
976 --- nfs-utils-1.0.8/utils/gssd/write_bytes.h~CITI_NFS4_ALL 2006-04-20 12:41:16.867750000 -0400
977 +++ nfs-utils-1.0.8-kwc/utils/gssd/write_bytes.h 2006-04-20 12:41:16.905712000 -0400
978 @@ -63,6 +63,19 @@ write_buffer(char **p, char *end, gss_bu
983 +write_oid(char **p, char *end, gss_OID_desc *arg)
985 + int len = (int)arg->length; /* make an int out of size_t */
986 + if (WRITE_BYTES(p, end, len))
988 + if (*p + arg->length > end)
990 + memcpy(*p, arg->elements, len);
996 get_bytes(char **ptr, const char *end, void *res, int len)
998 diff -puN utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL utils/gssd/svcgssd_proc.c
999 --- nfs-utils-1.0.8/utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL 2006-04-20 12:41:17.109514000 -0400
1000 +++ nfs-utils-1.0.8-kwc/utils/gssd/svcgssd_proc.c 2006-04-20 12:41:17.133514000 -0400
1001 @@ -220,8 +220,21 @@ get_ids(gss_name_t client_name, gss_OID
1002 nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
1003 res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
1005 - printerr(0, "WARNING: get_ids: unable to map "
1006 - "name '%s' to a uid\n", sname);
1008 + * -ENOENT means there was no mapping, any other error
1009 + * value means there was an error trying to do the
1012 + if (res == -ENOENT) {
1013 + cred->cr_uid = -2; /* XXX */
1014 + cred->cr_gid = -2; /* XXX */
1015 + cred->cr_groups[0] = -2;/* XXX */
1016 + cred->cr_ngroups = 1;
1020 + printerr(0, "WARNING: get_ids: failed to map name '%s' "
1021 + "to uid/gid: %s\n", sname, strerror(-res));