3 The complete set of CITI nfs-utils patches rolled into one patch.
5 Changes since 1.1.0-CITI_NFS4_ALL-2:
7 * Update to nfs-utils-1.1.1
9 * Patch from Steve Langasek <vorlon@debian.org> and
10 Steinar H. Gunderson <sesse@debian.org> fixing segfault problem on
11 64-bit platforms introduced by the xlog cleanup (re-using va_list).
18 -nfs-utils-1.1.1-kwc/aclocal.m4 | 569 +++--------
19 -nfs-utils-1.1.1-kwc/config.guess | 34
20 -nfs-utils-1.1.1-kwc/config.sub | 24
21 -nfs-utils-1.1.1-kwc/configure | 1195 ++++++++++--------------
22 -nfs-utils-1.1.1-kwc/ltmain.sh | 147 +-
23 nfs-utils-1.1.1-kwc/support/nfs/xlog.c | 8
24 nfs-utils-1.1.1-kwc/utils/gssd/context.h | 6
25 nfs-utils-1.1.1-kwc/utils/gssd/context_lucid.c | 391 +++++++
26 nfs-utils-1.1.1-kwc/utils/gssd/context_mit.c | 256 ++++-
27 nfs-utils-1.1.1-kwc/utils/gssd/gssd.c | 8
28 nfs-utils-1.1.1-kwc/utils/gssd/gssd.h | 3
29 nfs-utils-1.1.1-kwc/utils/gssd/gssd_main_loop.c | 20
30 nfs-utils-1.1.1-kwc/utils/gssd/gssd_proc.c | 119 +-
31 nfs-utils-1.1.1-kwc/utils/gssd/krb5_util.c | 231 +++-
32 nfs-utils-1.1.1-kwc/utils/gssd/krb5_util.h | 2
33 nfs-utils-1.1.1-kwc/utils/gssd/svcgssd_proc.c | 84 +
34 16 files changed, 1786 insertions(+), 1311 deletions(-)
36 diff -puN support/nfs/xlog.c~CITI_NFS4_ALL support/nfs/xlog.c
37 --- nfs-utils-1.1.1/support/nfs/xlog.c~CITI_NFS4_ALL 2007-10-23 14:17:18.316202000 -0400
38 +++ nfs-utils-1.1.1-kwc/support/nfs/xlog.c 2007-10-23 14:17:18.385133000 -0400
39 @@ -133,9 +133,13 @@ xlog_enabled(int fac)
41 xlog_backend(int kind, const char *fmt, va_list args)
45 if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
48 + va_copy(args2, args);
53 @@ -172,10 +176,12 @@ xlog_backend(int kind, const char *fmt,
54 fprintf(stderr, "%s: ", log_name);
57 - vfprintf(stderr, fmt, args);
58 + vfprintf(stderr, fmt, args2);
59 fprintf(stderr, "\n");
67 diff -puN utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL utils/gssd/svcgssd_proc.c
68 --- nfs-utils-1.1.1/utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL 2007-10-23 14:17:18.488030000 -0400
69 +++ nfs-utils-1.1.1-kwc/utils/gssd/svcgssd_proc.c 2007-10-23 14:17:18.505013000 -0400
74 +#include "gss_oids.h"
76 extern char * mech2file(gss_OID mech);
77 #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
78 @@ -66,8 +67,30 @@ struct svc_cred {
82 +get_krb5_hostbased_name (gss_buffer_desc name, char **hostbased_name)
84 + char *p, *sname = NULL;
85 + if (strchr(name.value, '@') && strchr(name.value, '/')) {
86 + if (!(sname = calloc(name.length, 1))) {
87 + printerr(0, "ERROR: get_krb5_hostbased_name failed "
88 + "to allocate %d bytes\n", name.length);
91 + /* read in name and instance and replace '/' with '@' */
92 + sscanf(name.value, "%[^@]", sname);
93 + p = strchr(sname, '/');
96 + *hostbased_name = sname;
103 do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
104 - gss_OID mech, gss_buffer_desc *context_token)
105 + gss_OID mech, gss_buffer_desc *context_token,
110 @@ -91,8 +114,9 @@ do_svc_downcall(gss_buffer_desc *out_han
111 qword_printint(f, cred->cr_gid);
112 qword_printint(f, cred->cr_ngroups);
113 printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d, "
114 - "uid: %d, gid: %d, num aux grps: %d:\n",
115 + "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
116 fname, out_handle->length, context_token->length, 0x7fffffff,
117 + client_name ? client_name : "<null>",
118 cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
119 for (i=0; i < cred->cr_ngroups; i++) {
120 qword_printint(f, cred->cr_groups[i]);
121 @@ -100,6 +124,8 @@ do_svc_downcall(gss_buffer_desc *out_han
123 qword_print(f, fname);
124 qword_printhex(f, context_token->value, context_token->length);
126 + qword_print(f, client_name);
130 @@ -294,6 +320,45 @@ print_hexl(const char *description, unsi
135 +get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
136 + char **hostbased_name)
138 + u_int32_t maj_stat, min_stat;
139 + gss_buffer_desc name;
140 + gss_OID name_type = GSS_C_NO_OID;
144 + /* get the client name and for service principals only
145 + * add it after the context (service name used for
146 + * authenticating callbacks) */
147 + maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
148 + if (maj_stat != GSS_S_COMPLETE) {
149 + pgsserr("get_hostbased_client_name: gss_display_name",
150 + maj_stat, min_stat, mech);
153 + if (name.length >= 0xffff) { /* be certain name.length+1 doesn't overflow */
154 + printerr(0, "ERROR: get_hostbased_client_name: "
155 + "received gss_name is too long (%d bytes)\n",
159 + /* For Kerberos, transform the NT_KRB5_PRINCIPAL to
160 + * NT_HOSTBASED_SERVICE */
161 + if (g_OID_equal(&krb5oid, mech)) {
162 + if (!get_krb5_hostbased_name(name, &cname))
163 + *hostbased_name = cname;
165 + /* For SPKM3, do ??? */
168 + gss_release_buffer(&min_stat, &name);
174 handle_nullreq(FILE *f) {
175 /* XXX initialize to a random integer to reduce chances of unnecessary
176 @@ -320,6 +385,7 @@ handle_nullreq(FILE *f) {
177 static char *lbuf = NULL;
178 static int lbuflen = 0;
180 + char *hostbased_name = NULL;
182 printerr(1, "handling null request\n");
184 @@ -385,8 +451,12 @@ handle_nullreq(FILE *f) {
185 gss_release_name(&ignore_min_stat, &client_name);
188 - gss_release_name(&ignore_min_stat, &client_name);
190 + if (get_hostbased_client_name(client_name, mech, &hostbased_name)) {
191 + /* get_hostbased_client_name() prints error msg */
192 + maj_stat = GSS_S_BAD_NAME; /* XXX ? */
193 + gss_release_name(&ignore_min_stat, &client_name);
197 /* Context complete. Pass handle_seq in out_handle to use
198 * for context lookup in the kernel. */
199 @@ -400,12 +470,14 @@ handle_nullreq(FILE *f) {
200 printerr(0, "WARNING: handle_nullreq: "
201 "serialize_context_for_kernel failed\n");
202 maj_stat = GSS_S_FAILURE;
203 + gss_release_name(&ignore_min_stat, &client_name);
206 /* We no longer need the gss context */
207 gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
209 - do_svc_downcall(&out_handle, &cred, mech, &ctx_token);
210 + do_svc_downcall(&out_handle, &cred, mech, &ctx_token, hostbased_name);
211 + gss_release_name(&ignore_min_stat, &client_name);
213 send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
214 &out_handle, &out_tok);
215 @@ -414,6 +486,8 @@ out:
216 free(ctx_token.value);
217 if (out_tok.value != NULL)
218 gss_release_buffer(&ignore_min_stat, &out_tok);
219 + if (hostbased_name)
220 + free(hostbased_name);
221 printerr(1, "finished handling null request\n");
224 diff -puN utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL utils/gssd/gssd_main_loop.c
225 --- nfs-utils-1.1.1/utils/gssd/gssd_main_loop.c~CITI_NFS4_ALL 2007-10-23 14:17:18.606911000 -0400
226 +++ nfs-utils-1.1.1-kwc/utils/gssd/gssd_main_loop.c 2007-10-23 14:17:18.878793000 -0400
227 @@ -98,7 +98,7 @@ gssd_run()
230 struct sigaction dn_act;
234 /* Taken from linux/Documentation/dnotify.txt: */
235 dn_act.sa_sigaction = dir_notify_handler;
236 @@ -114,6 +114,19 @@ gssd_run()
237 fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
238 fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
240 + if ((fd_cb = open(pipefs_nfscbdir, O_RDONLY)) == -1) {
241 + /* could be an older kernel or a newer one doing NFS 4.1 */
242 + if (errno != ENOENT)
243 + printerr(0, "WARNING: failed to open %s: %s\n",
244 + pipefs_nfscbdir, strerror(errno));
245 + /* ignore processing callback directory */
246 + memset(pipefs_nfscbdir, '\0', sizeof(pipefs_nfscbdir));
248 + fcntl(fd_cb, F_SETSIG, DNOTIFY_SIGNAL);
249 + fcntl(fd_cb, F_NOTIFY,
250 + DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
255 printerr(1, "beginning poll\n");
256 @@ -121,8 +134,7 @@ gssd_run()
257 while (dir_changed) {
259 if (update_client_list()) {
260 - printerr(0, "ERROR: couldn't update "
262 + /* Error msg is already printed */
266 @@ -141,5 +153,7 @@ gssd_run()
274 diff -puN utils/gssd/gssd_proc.c~CITI_NFS4_ALL utils/gssd/gssd_proc.c
275 --- nfs-utils-1.1.1/utils/gssd/gssd_proc.c~CITI_NFS4_ALL 2007-10-23 14:17:18.662855000 -0400
276 +++ nfs-utils-1.1.1-kwc/utils/gssd/gssd_proc.c 2007-10-23 14:17:19.021793000 -0400
277 @@ -102,7 +102,7 @@ int pollsize; /* the size of pollaray (
278 /* XXX buffer problems: */
280 read_service_info(char *info_file_name, char **servicename, char **servername,
281 - int *prog, int *vers, char **protocol) {
282 + int *prog, int *vers, char **protocol, int *port) {
283 #define INFOBUFLEN 256
284 char buf[INFOBUFLEN];
285 static char dummy[128];
286 @@ -112,6 +112,9 @@ read_service_info(char *info_file_name,
290 + char princname[128];
295 struct hostent *ent = NULL;
296 @@ -136,19 +139,33 @@ read_service_info(char *info_file_name,
297 service, program, version,
301 if (numfields == 5) {
302 strcpy(protoname, "tcp");
303 } else if (numfields != 6) {
307 + princname[0] = '\0';
308 + if ((p = strstr(buf, "principal name:")) != NULL)
309 + sscanf(p, "principal name: %127s\n", princname);
311 + if ((p = strstr(buf, "port")) != NULL)
312 + sscanf(p, "port: %127s\n", cb_port);
314 /* check service, program, and version */
315 - if(memcmp(service, "nfs", 3)) return -1;
316 + if (memcmp(service, "nfs", 3))
318 *prog = atoi(program + 1); /* skip open paren */
319 *vers = atoi(version);
320 - if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
323 + if (strlen(service) == 3 && !memcmp(service, "nfs", 3)) {
324 + if ((*prog != 100003) || ((*vers != 2) && (*vers != 3) &&
327 + } else if (!memcmp(service, "nfs4_cb", 7)) {
332 /* create service name */
333 inaddr = inet_addr(address);
334 @@ -159,7 +176,12 @@ read_service_info(char *info_file_name,
335 if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
337 memcpy(*servername, ent->h_name, strlen(ent->h_name));
338 - snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
339 + if (princname[0] != '\0')
340 + printerr(2, "info file contains princname=%s\n", princname);
342 + snprintf(buf, INFOBUFLEN, "nfs@%s", ent->h_name);
343 + if (cb_port[0] != '\0')
344 + *port = atoi(cb_port);
345 if (!(*servicename = calloc(strlen(buf) + 1, 1)))
347 memcpy(*servicename, buf, strlen(buf));
348 @@ -219,9 +241,9 @@ out:
350 process_clnt_dir_files(struct clnt_info * clp)
354 - char info_file_name[32];
355 + char kname[PATH_MAX];
356 + char sname[PATH_MAX];
357 + char info_file_name[PATH_MAX];
359 if (clp->krb5_fd == -1) {
360 snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
361 @@ -231,14 +253,14 @@ process_clnt_dir_files(struct clnt_info
362 snprintf(sname, sizeof(sname), "%s/spkm3", clp->dirname);
363 clp->spkm3_fd = open(sname, O_RDWR);
365 - if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
366 + if ((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
368 snprintf(info_file_name, sizeof(info_file_name), "%s/info",
370 if ((clp->servicename == NULL) &&
371 read_service_info(info_file_name, &clp->servicename,
372 &clp->servername, &clp->prog, &clp->vers,
374 + &clp->protocol, &clp->port))
378 @@ -288,17 +310,17 @@ insert_clnt_poll(struct clnt_info *clp)
382 -process_clnt_dir(char *dir)
383 +process_clnt_dir(char *dir, char *pdir)
385 struct clnt_info * clp;
387 if (!(clp = insert_new_clnt()))
388 goto fail_destroy_client;
390 - if (!(clp->dirname = calloc(strlen(dir) + 1, 1))) {
391 + if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 1, 1))) {
392 goto fail_destroy_client;
394 - memcpy(clp->dirname, dir, strlen(dir));
395 + sprintf(clp->dirname, "%s/%s", pdir, dir);
396 if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) {
397 printerr(0, "ERROR: can't open %s: %s\n",
398 clp->dirname, strerror(errno));
399 @@ -342,16 +364,24 @@ init_client_list(void)
400 * directories, since the DNOTIFY could have been in there.
403 -update_old_clients(struct dirent **namelist, int size)
404 +update_old_clients(struct dirent **namelist, int size, char *pdir)
406 struct clnt_info *clp;
409 + char fname[PATH_MAX];
411 for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
412 + /* only compare entries in the global list that are from the
413 + * same pipefs parent directory as "pdir"
415 + if (strncmp(clp->dirname, pdir, strlen(pdir)) != 0) break;
418 for (i=0; i < size; i++) {
419 - if (!strcmp(clp->dirname, namelist[i]->d_name)) {
420 + snprintf(fname, sizeof(fname), "%s/%s",
421 + pdir, namelist[i]->d_name);
422 + if (strcmp(clp->dirname, fname) == 0) {
426 @@ -372,47 +402,72 @@ update_old_clients(struct dirent **namel
428 /* Search for a client by directory name, return 1 if found, 0 otherwise */
430 -find_client(char *dirname)
431 +find_client(char *dirname, char *pdir)
433 struct clnt_info *clp;
434 + char fname[PATH_MAX];
436 - for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next)
437 - if (!strcmp(clp->dirname, dirname))
438 + for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
439 + snprintf(fname, sizeof(fname), "%s/%s", pdir, dirname);
440 + if (strcmp(clp->dirname, fname) == 0)
446 -/* Used to read (and re-read) list of clients, set up poll array. */
448 -update_client_list(void)
450 +process_pipedir(char *pipe_name)
452 struct dirent **namelist;
455 - if (chdir(pipefs_nfsdir) < 0) {
456 + if (chdir(pipe_name) < 0) {
457 printerr(0, "ERROR: can't chdir to %s: %s\n",
458 - pipefs_nfsdir, strerror(errno));
459 + pipe_name, strerror(errno));
463 - j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
464 + j = scandir(pipe_name, &namelist, NULL, alphasort);
466 printerr(0, "ERROR: can't scandir %s: %s\n",
467 - pipefs_nfsdir, strerror(errno));
468 + pipe_name, strerror(errno));
471 - update_old_clients(namelist, j);
473 + update_old_clients(namelist, j, pipe_name);
474 for (i=0; i < j; i++) {
475 if (i < FD_ALLOC_BLOCK
476 && !strncmp(namelist[i]->d_name, "clnt", 4)
477 - && !find_client(namelist[i]->d_name))
478 - process_clnt_dir(namelist[i]->d_name);
479 + && !find_client(namelist[i]->d_name, pipe_name))
480 + process_clnt_dir(namelist[i]->d_name, pipe_name);
488 +/* Used to read (and re-read) list of clients, set up poll array. */
490 +update_client_list(void)
494 + retval = process_pipedir(pipefs_nfsdir);
496 + printerr(0, "ERROR: processing %s\n", pipefs_nfsdir);
498 + /* if we successfully processed nfsdir and callback directory exists
499 + * process any events in the callback directory
501 + if (retval == 0 && pipefs_nfscbdir[0] != '\0') {
502 + retval = process_pipedir(pipefs_nfscbdir);
504 + printerr(0, "ERROR: processing %s\n", pipefs_nfscbdir);
511 do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
512 @@ -587,6 +642,8 @@ int create_auth_rpc_client(struct clnt_i
513 clp->servername, uid);
517 + ((struct sockaddr_in *)a->ai_addr)->sin_port = htons(clp->port);
518 if (a->ai_protocol == IPPROTO_TCP) {
519 if ((rpc_clnt = clnttcp_create(
520 (struct sockaddr_in *) a->ai_addr,
521 @@ -677,7 +734,7 @@ handle_krb5_upcall(struct clnt_info *clp
523 int create_resp = -1;
525 - printerr(1, "handling krb5 upcall\n");
526 + printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
530 @@ -787,7 +844,7 @@ handle_spkm3_upcall(struct clnt_info *cl
531 struct authgss_private_data pd;
532 gss_buffer_desc token;
534 - printerr(2, "handling spkm3 upcall\n");
535 + printerr(2, "handling spkm3 upcall (%s)\n", clp->dirname);
539 diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c
540 --- nfs-utils-1.1.1/utils/gssd/gssd.c~CITI_NFS4_ALL 2007-10-23 14:17:18.789793000 -0400
541 +++ nfs-utils-1.1.1-kwc/utils/gssd/gssd.c 2007-10-23 14:17:19.183793000 -0400
544 char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
545 char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
546 +char pipefs_nfscbdir[PATH_MAX] = GSSD_PIPEFS_DIR;
547 char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
548 char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
549 int use_memcache = 0;
550 @@ -140,6 +141,10 @@ main(int argc, char *argv[])
551 pipefs_dir, GSSD_SERVICE_NAME);
552 if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
553 errx(1, "pipefs_nfsdir path name too long");
554 + snprintf(pipefs_nfscbdir, sizeof(pipefs_nfscbdir), "%s/%s",
555 + pipefs_dir, GSSD_NFSCB_NAME);
556 + if (pipefs_nfscbdir[sizeof(pipefs_nfscbdir)-1] != '\0')
557 + errx(1, "pipefs_nfscbdir path name too long");
559 if ((progname = strrchr(argv[0], '/')))
561 @@ -165,6 +170,9 @@ main(int argc, char *argv[])
562 signal(SIGTERM, sig_die);
563 signal(SIGHUP, sig_hup);
565 + /* Determine Kerberos information from the kernel */
566 + gssd_obtain_kernel_krb5_info();
569 printerr(0, "gssd_run returned!\n");
571 diff -puN utils/gssd/gssd.h~CITI_NFS4_ALL utils/gssd/gssd.h
572 --- nfs-utils-1.1.1/utils/gssd/gssd.h~CITI_NFS4_ALL 2007-10-23 14:17:18.846794000 -0400
573 +++ nfs-utils-1.1.1-kwc/utils/gssd/gssd.h 2007-10-23 14:17:18.957793000 -0400
575 #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine"
576 #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
577 #define GSSD_SERVICE_NAME "nfs"
578 +#define GSSD_NFSCB_NAME "nfsd4_cb"
579 #define GSSD_SERVICE_NAME_LEN 3
582 @@ -60,6 +61,7 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
584 extern char pipefs_dir[PATH_MAX];
585 extern char pipefs_nfsdir[PATH_MAX];
586 +extern char pipefs_nfscbdir[PATH_MAX];
587 extern char keytabfile[PATH_MAX];
588 extern char ccachedir[PATH_MAX];
589 extern int use_memcache;
590 @@ -80,6 +82,7 @@ struct clnt_info {
593 int spkm3_poll_index;
597 void init_client_list(void);
598 diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c
599 --- nfs-utils-1.1.1/utils/gssd/krb5_util.c~CITI_NFS4_ALL 2007-10-23 14:17:19.109793000 -0400
600 +++ nfs-utils-1.1.1-kwc/utils/gssd/krb5_util.c 2007-10-23 14:17:19.198793000 -0400
603 #include <sys/param.h>
605 +#include <sys/types.h>
606 #include <sys/stat.h>
607 #include <sys/socket.h>
608 #include <arpa/inet.h>
616 #include <gssapi/gssapi.h>
618 /* Global list of principals/cache file names for machine credentials */
619 struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
621 +/* Encryption types supported by the kernel rpcsec_gss code */
622 +int num_krb5_enctypes = 0;
623 +krb5_enctype *krb5_enctypes = NULL;
625 /*==========================*/
626 /*=== Internal routines ===*/
627 /*==========================*/
628 @@ -256,58 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
633 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
635 - * this routine obtains a credentials handle via gss_acquire_cred()
636 - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
637 - * types negotiated.
639 - * XXX Should call some function to determine the enctypes supported
640 - * by the kernel. (Only need to do that once!)
643 - * 0 => all went well
644 - * -1 => there was an error
648 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
650 - u_int maj_stat, min_stat;
651 - gss_cred_id_t credh;
652 - gss_OID_set_desc desired_mechs;
653 - krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
654 - int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
656 - /* We only care about getting a krb5 cred */
657 - desired_mechs.count = 1;
658 - desired_mechs.elements = &krb5oid;
660 - maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
661 - &desired_mechs, GSS_C_INITIATE,
662 - &credh, NULL, NULL);
664 - if (maj_stat != GSS_S_COMPLETE) {
665 - pgsserr("gss_acquire_cred",
666 - maj_stat, min_stat, &krb5oid);
670 - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
671 - num_enctypes, &enctypes);
672 - if (maj_stat != GSS_S_COMPLETE) {
673 - pgsserr("gss_set_allowable_enctypes",
674 - maj_stat, min_stat, &krb5oid);
675 - gss_release_cred(&min_stat, &credh);
682 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
685 * Obtain credentials via a key in the keytab given
686 * a keytab handle and a gssd_k5_kt_princ structure.
687 @@ -879,6 +833,56 @@ out:
692 + * Parse the supported encryption type information
695 +parse_enctypes(char *enctypes)
698 + char *curr, *comma;
701 + /* Just in case this ever gets called more than once */
702 + if (krb5_enctypes != NULL) {
703 + free(krb5_enctypes);
704 + krb5_enctypes = NULL;
705 + num_krb5_enctypes = 0;
708 + /* count the number of commas */
709 + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
710 + comma = strchr(curr, ',');
716 + /* If no more commas and we're not at the end, there's one more value */
720 + /* Empty string, return an error */
724 + /* Allocate space for enctypes array */
725 + if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
729 + /* Now parse each value into the array */
730 + for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
731 + krb5_enctypes[i++] = atoi(curr);
732 + comma = strchr(curr, ',');
737 + num_krb5_enctypes = n;
741 /*==========================*/
742 /*=== External routines ===*/
743 /*==========================*/
744 @@ -1129,3 +1133,126 @@ gssd_k5_err_msg(krb5_context context, kr
745 return error_message(code);
749 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
751 + * this routine obtains a credentials handle via gss_acquire_cred()
752 + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
753 + * types negotiated.
756 + * 0 => all went well
757 + * -1 => there was an error
761 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
763 + u_int maj_stat, min_stat;
764 + gss_cred_id_t credh;
765 + gss_OID_set_desc desired_mechs;
766 + krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
767 + int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
769 + /* We only care about getting a krb5 cred */
770 + desired_mechs.count = 1;
771 + desired_mechs.elements = &krb5oid;
773 + maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
774 + &desired_mechs, GSS_C_INITIATE,
775 + &credh, NULL, NULL);
777 + if (maj_stat != GSS_S_COMPLETE) {
778 + pgsserr("gss_acquire_cred",
779 + maj_stat, min_stat, &krb5oid);
784 + * If we failed for any reason to produce global
785 + * list of supported enctypes, use local default here.
787 + if (krb5_enctypes == NULL)
788 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
789 + &krb5oid, num_enctypes, &enctypes);
791 + maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
792 + &krb5oid, num_krb5_enctypes,
794 + if (maj_stat != GSS_S_COMPLETE) {
795 + pgsserr("gss_set_allowable_enctypes",
796 + maj_stat, min_stat, &krb5oid);
803 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
806 + * Obtain supported enctypes from kernel.
807 + * Set defaults if info is not available.
810 +gssd_obtain_kernel_krb5_info(void)
812 + char enctype_file_name[128];
814 + char enctypes[128];
817 + int use_default_enctypes = 0;
818 + int nbytes, numfields;
819 + char default_enctypes[] = "1,3,2";
822 + snprintf(enctype_file_name, sizeof(enctype_file_name),
823 + "%s/%s", pipefs_dir, "krb5_info");
825 + if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
826 + printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
827 + "Unable to open '%s'. Unable to determine "
828 + "Kerberos encryption types supported by the "
829 + "kernel; using defaults (%s).\n",
830 + enctype_file_name, default_enctypes);
831 + use_default_enctypes = 1;
834 + memset(buf, 0, sizeof(buf));
835 + if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) {
836 + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
837 + "Error reading Kerberos encryption type "
838 + "information file '%s'; using defaults (%s).\n",
839 + enctype_file_name, default_enctypes);
840 + use_default_enctypes = 1;
845 + numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned);
846 + if (numfields < 1) {
847 + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
848 + "error parsing Kerberos encryption type "
849 + "information from file '%s'; using defaults (%s).\n",
850 + enctype_file_name, default_enctypes);
851 + use_default_enctypes = 1;
854 + if (nbytes > nscanned) {
855 + printerr(2, "gssd_obtain_kernel_krb5_info: "
856 + "Ignoring extra information, '%s', from '%s'\n",
857 + buf+nscanned, enctype_file_name);
861 + if (use_default_enctypes)
862 + strcpy(enctypes, default_enctypes);
864 + if ((code = parse_enctypes(enctypes)) != 0) {
865 + printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
866 + "parse_enctypes%s failed with code %d\n",
867 + use_default_enctypes ? " (with default enctypes)" : "",
871 diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h
872 --- nfs-utils-1.1.1/utils/gssd/krb5_util.h~CITI_NFS4_ALL 2007-10-23 14:17:19.166793000 -0400
873 +++ nfs-utils-1.1.1-kwc/utils/gssd/krb5_util.h 2007-10-23 14:17:19.206793000 -0400
874 @@ -26,6 +26,8 @@ int gssd_refresh_krb5_machine_credentia
875 struct gssd_k5_kt_princ *ple);
877 gssd_k5_err_msg(krb5_context context, krb5_error_code code);
878 +void gssd_obtain_kernel_krb5_info(void);
881 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
882 int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
883 diff -puN utils/gssd/context.h~CITI_NFS4_ALL utils/gssd/context.h
884 --- nfs-utils-1.1.1/utils/gssd/context.h~CITI_NFS4_ALL 2007-10-23 14:17:19.330737000 -0400
885 +++ nfs-utils-1.1.1-kwc/utils/gssd/context.h 2007-10-23 14:17:19.458609000 -0400
888 - Copyright (c) 2004 The Regents of the University of Michigan.
889 + Copyright (c) 2004-2006 The Regents of the University of Michigan.
892 Redistribution and use in source and binary forms, with or without
894 /* Hopefully big enough to hold any serialized context */
895 #define MAX_CTX_LEN 4096
897 +/* New context format flag values */
898 +#define KRB5_CTX_FLAG_INITIATOR 0x00000001
899 +#define KRB5_CTX_FLAG_CFX 0x00000002
900 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
902 int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
904 diff -puN utils/gssd/context_lucid.c~CITI_NFS4_ALL utils/gssd/context_lucid.c
905 --- nfs-utils-1.1.1/utils/gssd/context_lucid.c~CITI_NFS4_ALL 2007-10-23 14:17:19.386681000 -0400
906 +++ nfs-utils-1.1.1-kwc/utils/gssd/context_lucid.c 2007-10-23 14:17:19.465602000 -0400
912 #include "gss_util.h"
913 #include "gss_oids.h"
914 #include "err_util.h"
915 @@ -113,15 +114,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc
916 * Note that the rfc1964 version only supports DES enctypes.
918 if (lctx->rfc1964_kd.ctx_key.type != 4) {
919 - printerr(1, "prepare_krb5_rfc1964_buffer: "
920 - "overriding heimdal keytype (%d => %d)\n",
921 - lctx->rfc1964_kd.ctx_key.type, 4);
922 + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
923 + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
924 lctx->rfc1964_kd.ctx_key.type = 4;
927 - printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
928 - "enctype %d and length %d\n",
929 - lctx->rfc1964_kd.ctx_key.type,
930 + printerr(2, "%s: serializing keys with enctype %d and length %d\n",
931 + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
932 lctx->rfc1964_kd.ctx_key.length);
934 /* derive the encryption key and copy it into buffer */
935 @@ -152,15 +151,361 @@ out_err:
940 -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
941 - gss_buffer_desc *buf)
942 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
943 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
946 +#define KG_USAGE_SEAL 22
947 +#define KG_USAGE_SIGN 23
948 +#define KG_USAGE_SEQ 24
951 +#define KG_USAGE_ACCEPTOR_SEAL 22
952 +#define KG_USAGE_ACCEPTOR_SIGN 23
953 +#define KG_USAGE_INITIATOR_SEAL 24
954 +#define KG_USAGE_INITIATOR_SIGN 25
956 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
958 + SEAL_ALG_NONE = 0xffff,
959 + SEAL_ALG_DES = 0x0000,
960 + SEAL_ALG_1 = 0x0001, /* not published */
961 + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
962 + SEAL_ALG_DES3KD = 0x0002
965 +#define KEY_USAGE_SEED_ENCRYPTION 0xAA
966 +#define KEY_USAGE_SEED_INTEGRITY 0x55
967 +#define KEY_USAGE_SEED_CHECKSUM 0x99
970 +/* Flags for version 2 context flags */
971 +#define KRB5_CTX_FLAG_INITIATOR 0x00000001
972 +#define KRB5_CTX_FLAG_CFX 0x00000002
973 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
975 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
976 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
978 + * We don't have "legal" access to these MIT-only
979 + * structures located in libk5crypto
981 +extern void krb5int_enc_arcfour;
982 +extern void krb5int_enc_des3;
983 +extern void krb5int_enc_aes128;
984 +extern void krb5int_enc_aes256;
985 +extern int krb5_derive_key();
988 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
990 - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
992 + memset(kout, '\0', sizeof(kout));
994 + kout->enctype = lin->type;
995 + kout->length = lin->length;
996 + kout->contents = lin->data;
998 + kout->keytype = lin->type;
999 + kout->keyvalue.length = lin->length;
1000 + kout->keyvalue.data = lin->data;
1005 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
1007 + memset(lout, '\0', sizeof(lout));
1009 + lout->type = kin->enctype;
1010 + lout->length = kin->length;
1011 + lout->data = kin->contents;
1013 + lout->type = kin->keytype;
1014 + lout->length = kin->keyvalue.length;
1015 + memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
1019 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
1020 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
1021 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
1022 +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
1024 + * Function to derive a new key from a given key and given constant data.
1026 +static krb5_error_code
1027 +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
1028 + int usage, char extra)
1030 + krb5_error_code code;
1031 + unsigned char constant_data[K5CLENGTH];
1035 + krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
1036 +#ifdef HAVE_HEIMDAL
1037 + krb5_context kcontext;
1038 + krb5_keyblock *outkey;
1042 + * XXX Hack alert. We don't have "legal" access to these
1043 + * values and structures located in libk5crypto
1045 + switch (in->type) {
1046 + case ENCTYPE_DES3_CBC_SHA1:
1048 + case ENCTYPE_DES3_CBC_RAW:
1052 + enc = &krb5int_enc_des3;
1055 + case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
1058 + enc = &krb5int_enc_aes128;
1061 + case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
1064 + enc = &krb5int_enc_aes256;
1068 + code = KRB5_BAD_ENCTYPE;
1072 + /* allocate memory for output key */
1073 + if ((out->data = malloc(keylength)) == NULL) {
1077 + out->length = keylength;
1078 + out->type = in->type;
1080 + /* Convert to correct format for call to krb5_derive_key */
1081 + key_lucid_to_krb5(in, &kin);
1082 + key_lucid_to_krb5(out, &kout);
1084 + datain.data = (char *) constant_data;
1085 + datain.length = K5CLENGTH;
1087 + ((char *)(datain.data))[0] = (usage>>24)&0xff;
1088 + ((char *)(datain.data))[1] = (usage>>16)&0xff;
1089 + ((char *)(datain.data))[2] = (usage>>8)&0xff;
1090 + ((char *)(datain.data))[3] = usage&0xff;
1092 + ((char *)(datain.data))[4] = (char) extra;
1095 + code = krb5_derive_key(enc, &kin, &kout, &datain);
1097 + if ((code = krb5_init_context(&kcontext))) {
1099 + code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
1107 + key_krb5_to_lucid(&kout, out);
1109 + key_krb5_to_lucid(outkey, out);
1110 + krb5_free_keyblock(kcontext, outkey);
1111 + krb5_free_context(kcontext);
1116 + printerr(0, "ERROR: %s: returning error %d (%s)\n",
1117 + __FUNCTION__, code, error_message(code));
1123 + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
1124 + * to send to the kernel for newer encryption types -- or for DES3.
1126 + * The new format is:
1128 + * u32 initiate; ( whether we are the initiator or not )
1131 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
1132 + * #define KRB5_CTX_FLAG_CFX 0x00000002
1133 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
1135 + * u32 enctype; ( encrption type of keys )
1136 + * u32 size_of_each_key; ( size of each key in bytes )
1137 + * u32 number_of_keys; ( N -- should always be 3 for now )
1138 + * keydata-1; ( Ke )
1139 + * keydata-2; ( Ki )
1140 + * keydata-3; ( Kc )
1144 +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
1145 + gss_buffer_desc *buf)
1148 + uint32_t v2_flags = 0;
1149 + gss_krb5_lucid_key_t enc_key;
1150 + gss_krb5_lucid_key_t derived_key;
1151 + gss_buffer_desc fakeoid;
1156 + memset(&enc_key, 0, sizeof(enc_key));
1157 + memset(&fakeoid, 0, sizeof(fakeoid));
1159 + if (!(buf->value = calloc(1, MAX_CTX_LEN)))
1162 + end = buf->value + MAX_CTX_LEN;
1165 + if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
1166 + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
1168 + if (lctx->initiate)
1169 + v2_flags |= KRB5_CTX_FLAG_INITIATOR;
1170 + if (lctx->protocol != 0)
1171 + v2_flags |= KRB5_CTX_FLAG_CFX;
1172 + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
1173 + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
1175 + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
1177 + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
1179 + /* Protocol 0 here implies DES3 or RC4 */
1180 + printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
1181 + if (lctx->protocol == 0) {
1182 + enctype = lctx->rfc1964_kd.ctx_key.type;
1183 +#ifdef HAVE_HEIMDAL
1185 + * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for
1186 + * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16).
1187 + * Force the Heimdal enctype to 6.
1189 + if (enctype == ENCTYPE_DES3_CBC_SHA1) {
1190 + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
1191 + __FUNCTION__, enctype, 6);
1196 + keysize = lctx->rfc1964_kd.ctx_key.length;
1197 + numkeys = 3; /* XXX is always gonna be three? */
1199 + if (lctx->cfx_kd.have_acceptor_subkey) {
1200 + enctype = lctx->cfx_kd.acceptor_subkey.type;
1201 + keysize = lctx->cfx_kd.acceptor_subkey.length;
1203 + enctype = lctx->cfx_kd.ctx_key.type;
1204 + keysize = lctx->cfx_kd.ctx_key.length;
1208 + printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
1209 + __FUNCTION__, numkeys, enctype, keysize);
1210 + if (WRITE_BYTES(&p, end, enctype)) goto out_err;
1211 + if (WRITE_BYTES(&p, end, keysize)) goto out_err;
1212 + if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
1214 + if (lctx->protocol == 0) {
1215 + /* derive and send down: Ke, Ki, and Kc */
1217 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
1218 + lctx->rfc1964_kd.ctx_key.length))
1222 + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
1223 + lctx->rfc1964_kd.ctx_key.length))
1227 + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
1229 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1231 + if (write_bytes(&p, end, derived_key.data,
1232 + derived_key.length))
1234 + free(derived_key.data);
1236 + gss_krb5_lucid_key_t *keyptr;
1237 + uint32_t sign_usage, seal_usage;
1239 + if (lctx->cfx_kd.have_acceptor_subkey)
1240 + keyptr = &lctx->cfx_kd.acceptor_subkey;
1242 + keyptr = &lctx->cfx_kd.ctx_key;
1244 + if (lctx->initiate == 1) {
1245 + sign_usage = KG_USAGE_INITIATOR_SIGN;
1246 + seal_usage = KG_USAGE_INITIATOR_SEAL;
1248 + sign_usage = KG_USAGE_ACCEPTOR_SIGN;
1249 + seal_usage = KG_USAGE_ACCEPTOR_SEAL;
1252 + /* derive and send down: Ke, Ki, and Kc */
1255 + if (derive_key_lucid(keyptr, &derived_key,
1256 + seal_usage, KEY_USAGE_SEED_ENCRYPTION))
1258 + if (write_bytes(&p, end, derived_key.data,
1259 + derived_key.length))
1261 + free(derived_key.data);
1264 + if (derive_key_lucid(keyptr, &derived_key,
1265 + seal_usage, KEY_USAGE_SEED_INTEGRITY))
1267 + if (write_bytes(&p, end, derived_key.data,
1268 + derived_key.length))
1270 + free(derived_key.data);
1273 + if (derive_key_lucid(keyptr, &derived_key,
1274 + sign_usage, KEY_USAGE_SEED_CHECKSUM))
1276 + if (write_bytes(&p, end, derived_key.data,
1277 + derived_key.length))
1279 + free(derived_key.data);
1282 + buf->length = p - (char *)buf->value;
1286 + printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
1290 + buf->value = NULL;
1293 + if (enc_key.data) {
1294 + free(enc_key.data);
1295 + enc_key.data = NULL;
1300 serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
1302 @@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1303 gss_krb5_lucid_context_v1_t *lctx = 0;
1306 - printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
1307 + printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
1308 maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
1310 if (maj_stat != GSS_S_COMPLETE) {
1311 @@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1315 - /* Now lctx points to a lucid context that we can send down to kernel */
1316 - if (lctx->protocol == 0)
1318 + * Now lctx points to a lucid context that we can send down to kernel
1320 + * Note: we send down different information to the kernel depending
1321 + * on the protocol version and the enctyption type.
1322 + * For protocol version 0 with all enctypes besides DES3, we use
1323 + * the original format. For protocol version != 0 or DES3, we
1324 + * send down the new style information.
1327 + if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
1328 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
1330 - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
1331 + retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
1333 maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
1334 if (maj_stat != GSS_S_COMPLETE) {
1335 @@ -206,8 +560,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1339 - printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
1340 - "failed (retcode = %d)\n", retcode);
1341 + printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
1342 + __FUNCTION__, retcode);
1346 @@ -217,4 +571,7 @@ out_err:
1347 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
1353 #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
1354 diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c
1355 --- nfs-utils-1.1.1/utils/gssd/context_mit.c~CITI_NFS4_ALL 2007-10-23 14:17:19.441626000 -0400
1356 +++ nfs-utils-1.1.1-kwc/utils/gssd/context_mit.c 2007-10-23 14:17:19.473594000 -0400
1359 - Copyright (c) 2004 The Regents of the University of Michigan.
1360 + Copyright (c) 2004-2006 The Regents of the University of Michigan.
1361 All rights reserved.
1363 Redistribution and use in source and binary forms, with or without
1369 #include <gssapi/gssapi.h>
1370 #include <rpc/rpc.h>
1371 #include <rpc/auth_gss.h>
1373 /* XXX argggg, there's gotta be a better way than just duplicating this
1374 * whole struct. Unfortunately, this is in a "private" header file,
1375 * so this is our best choice at this point :-/
1377 - * XXX Does this match the Heimdal definition? */
1380 typedef struct _krb5_gss_ctx_id_rec {
1381 unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */
1382 @@ -139,6 +139,124 @@ write_keyblock(char **p, char *end, stru
1386 + * XXX Hack alert! XXX Do NOT submit upstream!
1387 + * XXX Hack alert! XXX Do NOT submit upstream!
1389 + * We shouldn't be using these definitions
1391 + * XXX Hack alert! XXX Do NOT submit upstream!
1392 + * XXX Hack alert! XXX Do NOT submit upstream!
1395 +#define KG_USAGE_SEAL 22
1396 +#define KG_USAGE_SIGN 23
1397 +#define KG_USAGE_SEQ 24
1400 +#define KG_USAGE_ACCEPTOR_SEAL 22
1401 +#define KG_USAGE_ACCEPTOR_SIGN 23
1402 +#define KG_USAGE_INITIATOR_SEAL 24
1403 +#define KG_USAGE_INITIATOR_SIGN 25
1405 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
1407 + SEAL_ALG_NONE = 0xffff,
1408 + SEAL_ALG_DES = 0x0000,
1409 + SEAL_ALG_1 = 0x0001, /* not published */
1410 + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
1411 + SEAL_ALG_DES3KD = 0x0002
1414 +#define KEY_USAGE_SEED_ENCRYPTION 0xAA
1415 +#define KEY_USAGE_SEED_INTEGRITY 0x55
1416 +#define KEY_USAGE_SEED_CHECKSUM 0x99
1417 +#define K5CLENGTH 5
1419 +extern void krb5_enc_des3;
1420 +extern void krb5int_enc_des3;
1421 +extern void krb5int_enc_arcfour;
1422 +extern void krb5int_enc_aes128;
1423 +extern void krb5int_enc_aes256;
1424 +extern int krb5_derive_key();
1427 + * XXX Hack alert! XXX Do NOT submit upstream!
1428 + * XXX Hack alert! XXX Do NOT submit upstream!
1430 + * We should be passing down a single key to the kernel
1431 + * and it should be deriving the other keys. We cannot
1432 + * depend on any of this stuff being accessible in the
1435 + * XXX Hack alert! XXX Do NOT submit upstream!
1436 + * XXX Hack alert! XXX Do NOT submit upstream!
1439 + * Function to derive a new key from a given key and given constant data.
1441 +static krb5_error_code
1442 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
1444 + krb5_error_code code;
1445 + unsigned char constant_data[K5CLENGTH];
1450 + switch (in->enctype) {
1451 +#ifdef ENCTYPE_DES3_CBC_RAW
1452 + case ENCTYPE_DES3_CBC_RAW:
1454 +/* Extra hack, the structure was renamed as rc4 was added... */
1455 +#if defined(ENCTYPE_ARCFOUR_HMAC)
1456 + enc = &krb5int_enc_des3;
1458 + enc = &krb5_enc_des3;
1462 +#ifdef ENCTYPE_ARCFOUR_HMAC
1463 + case ENCTYPE_ARCFOUR_HMAC:
1465 + enc = &krb5int_enc_arcfour;
1469 + code = KRB5_BAD_ENCTYPE;
1473 + /* allocate memory for output key */
1474 + if ((out->contents = malloc(keylength)) == NULL) {
1478 + out->length = keylength;
1479 + out->enctype = in->enctype;
1481 + datain.data = (char *) constant_data;
1482 + datain.length = K5CLENGTH;
1484 + datain.data[0] = (usage>>24)&0xff;
1485 + datain.data[1] = (usage>>16)&0xff;
1486 + datain.data[2] = (usage>>8)&0xff;
1487 + datain.data[3] = usage&0xff;
1489 + datain.data[4] = (char) extra;
1491 + if ((code = krb5_derive_key(enc, in, out, &datain))) {
1492 + free(out->contents);
1493 + out->contents = NULL;
1498 + printerr(0, "ERROR: derive_key returning error %d (%s)\n",
1499 + code, error_message(code));
1504 * We really shouldn't know about glue-layer context structure, but
1505 * we need to get at the real krb5 context pointer. This should be
1506 * removed as soon as we say there is no support for MIT Kerberos
1507 @@ -154,48 +272,124 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
1509 krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
1511 - static int constant_one = 1;
1512 static int constant_zero = 0;
1513 + static int constant_one = 1;
1514 + static int constant_two = 2;
1515 uint32_t word_seq_send;
1516 + u_int64_t seq_send_64bit;
1517 + uint32_t v2_flags = 0;
1518 + krb5_keyblock derived_key;
1521 if (!(buf->value = calloc(1, MAX_CTX_LEN)))
1524 end = buf->value + MAX_CTX_LEN;
1526 - if (kctx->initiate) {
1527 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1530 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1532 - if (kctx->seed_init) {
1533 - if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1536 - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1538 - if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
1539 + switch (kctx->sealalg) {
1540 + case SEAL_ALG_DES:
1541 + /* Old format of context to the kernel */
1542 + if (kctx->initiate) {
1543 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1546 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1548 + if (kctx->seed_init) {
1549 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1552 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1554 + if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
1556 + if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
1557 + if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
1558 + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1559 + word_seq_send = kctx->seq_send;
1560 + if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
1561 + if (write_oid(&p, end, kctx->mech_used)) goto out_err;
1563 + printerr(2, "serialize_krb5_ctx: serializing keys with "
1564 + "enctype %d and length %d\n",
1565 + kctx->enc->enctype, kctx->enc->length);
1567 + if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1568 + if (write_keyblock(&p, end, kctx->seq)) goto out_err;
1570 + case SEAL_ALG_MICROSOFT_RC4:
1571 + case SEAL_ALG_DES3KD:
1572 + /* New format of context to the kernel */
1575 + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
1576 + * #define KRB5_CTX_FLAG_CFX 0x00000002
1577 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
1580 + * u32 size_of_each_key; ( size in bytes )
1581 + * u32 number_of_keys; ( N (assumed to be 3 for now) )
1582 + * keydata-1; ( Ke (Kenc for DES3) )
1583 + * keydata-2; ( Ki (Kseq for DES3) )
1584 + * keydata-3; ( Kc (derived checksum key) )
1586 + if (kctx->initiate) {
1587 + if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
1590 + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
1592 + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1594 + /* Only applicable flag for this is initiator */
1595 + if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
1596 + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
1598 + seq_send_64bit = kctx->seq_send;
1599 + if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
1601 + if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
1602 + if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
1604 + if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
1605 + printerr(2, "serialize_krb5_ctx: serializing %d keys with "
1606 + "enctype %d and size %d\n",
1607 + numkeys, kctx->enc->enctype, kctx->enc->length);
1610 + if (write_bytes(&p, end, kctx->enc->contents,
1611 + kctx->enc->length))
1615 + if (write_bytes(&p, end, kctx->enc->contents,
1616 + kctx->enc->length))
1620 + if (derive_key(kctx->seq, &derived_key,
1621 + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
1623 + if (write_bytes(&p, end, derived_key.contents,
1624 + derived_key.length))
1626 + free(derived_key.contents);
1629 + printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
1630 + "algorithm %d\n", kctx->sealalg);
1632 - if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
1633 - if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
1634 - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
1635 - word_seq_send = kctx->seq_send;
1636 - if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
1637 - if (write_oid(&p, end, kctx->mech_used)) goto out_err;
1639 - printerr(2, "serialize_krb5_ctx: serializing keys with "
1640 - "enctype %d and length %d\n",
1641 - kctx->enc->enctype, kctx->enc->length);
1643 - if (write_keyblock(&p, end, kctx->enc)) goto out_err;
1644 - if (write_keyblock(&p, end, kctx->seq)) goto out_err;
1647 buf->length = p - (char *)buf->value;
1651 printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
1652 - if (buf->value) free(buf->value);
1656 + buf->value = NULL;