]> git.pld-linux.org Git - packages/nfs-utils.git/blob - nfs-utils-1.0.8-CITI_NFS4_ALL-1.dif
- really fixed this time
[packages/nfs-utils.git] / nfs-utils-1.0.8-CITI_NFS4_ALL-1.dif
1
2
3 The complete set of CITI nfs-utils patches rolled into one patch.
4
5 Changes since 1.0.8-rc4-CITI_NFS4_ALL-3:
6
7  * Update to the final nfs-utils-1.0.8
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.
11
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
15    export.
16
17
18 ---
19
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(-)
30
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");
36  #endif
37  
38 +       if (gssd_check_mechs() != 0)
39 +               errx(1, "Problem with gssapi library");
40 +
41         if (!fg && daemon(0, 0) < 0)
42                 errx(1, "fork");
43  
44 @@ -154,6 +157,8 @@ main(int argc, char *argv[])
45  
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();
50  
51         gssd_run();
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)
57  
58         return (maj_stat == GSS_S_COMPLETE);
59  }
60 +
61 +int gssd_check_mechs(void)
62 +{
63 +       u_int32_t maj_stat, min_stat;
64 +       gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
65 +       int retval = -1;
66 +
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");
71 +               goto out;
72 +       }
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");
77 +               goto out;
78 +       }
79 +       maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
80 +       retval = 0;
81 +out:
82 +       return retval;
83 +}
84 +
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,
91         const gss_OID mech);
92 +int gssd_check_mechs(void);
93  
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");
100  #endif
101  
102 +       if (gssd_check_mechs() != 0) {
103 +               printerr(0, "ERROR: Problem with gssapi library\n");
104 +               exit(1);
105 +       }
106 +
107         if (!fg)
108                 mydaemon(0, 0);
109  
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
113 @@ -97,6 +97,7 @@
114  #include "config.h"
115  #include <sys/param.h>
116  #include <rpc/rpc.h>
117 +#include <sys/types.h>
118  #include <sys/stat.h>
119  #include <sys/socket.h>
120  #include <arpa/inet.h>
121 @@ -105,6 +106,7 @@
122  #include <stdlib.h>
123  #include <string.h>
124  #include <dirent.h>
125 +#include <fcntl.h>
126  #include <errno.h>
127  #include <time.h>
128  #include <gssapi/gssapi.h>
129 @@ -123,6 +125,10 @@
130  /* Global list of principals/cache file names for machine credentials */
131  struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
132  
133 +/* Encryption types supported by the kernel rpcsec_gss code */
134 +int num_krb5_enctypes = 0;
135 +krb5_enctype *krb5_enctypes = NULL;
136 +
137  /*==========================*/
138  /*===  Internal routines ===*/
139  /*==========================*/
140 @@ -261,51 +267,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
141  }
142  
143  
144 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
145 -/*
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.
149 - *
150 - * XXX Should call some function to determine the enctypes supported
151 - * by the kernel. (Only need to do that once!)
152 - *
153 - * Returns:
154 - *     0 => all went well
155 - *     -1 => there was an error
156 - */
157 -
158 -int
159 -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
160 -{
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]);
165 -
166 -       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
167 -                                   GSS_C_NULL_OID_SET, GSS_C_INITIATE,
168 -                                   &credh, NULL, NULL);
169 -
170 -       if (maj_stat != GSS_S_COMPLETE) {
171 -               pgsserr("gss_acquire_cred",
172 -                       maj_stat, min_stat, &krb5oid);
173 -               return -1;
174 -       }
175 -
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);
181 -               return -1;
182 -       }
183 -       sec->cred = credh;
184 -
185 -       return 0;
186 -}
187 -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
188 -
189  /*
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)
193  #endif
194  }
195  
196 +/*
197 + * Parse the supported encryption type information
198 + */
199 +static int
200 +parse_enctypes(char *enctypes)
201 +{
202 +       int n = 0;
203 +       char *curr, *comma;
204 +       int i;
205 +
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;
211 +       }
212 +
213 +       /* count the number of commas */
214 +       for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
215 +               comma = strchr(curr, ',');
216 +               if (comma != NULL)
217 +                       n++;
218 +               else
219 +                       break;
220 +       }
221 +       /* If no more commas and we're not at the end, there's one more value */
222 +       if (*curr != '\0')
223 +               n++;
224 +
225 +       /* Empty string, return an error */
226 +       if (n == 0)
227 +               return ENOENT;
228 +
229 +       /* Allocate space for enctypes array */
230 +       if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
231 +               return ENOMEM;
232 +       }
233 +
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, ',');
238 +               if (comma == NULL)
239 +                       break;
240 +       }
241 +
242 +       num_krb5_enctypes = n;
243 +       return 0;
244 +}
245 +
246  /*==========================*/
247  /*===  External routines ===*/
248  /*==========================*/
249 @@ -854,3 +865,123 @@ gssd_destroy_krb5_machine_creds(void)
250         krb5_free_context(context);
251  }
252  
253 +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
254 +/*
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.
258 + *
259 + * Returns:
260 + *     0 => all went well
261 + *     -1 => there was an error
262 + */
263 +
264 +int
265 +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
266 +{
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]);
272 +
273 +       /* We only care about getting a krb5 cred */
274 +       desired_mechs.count = 1;
275 +       desired_mechs.elements = &krb5oid;
276 +
277 +       maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
278 +                                   &desired_mechs, GSS_C_INITIATE,
279 +                                   &credh, NULL, NULL);
280 +
281 +       if (maj_stat != GSS_S_COMPLETE) {
282 +               pgsserr("gss_acquire_cred",
283 +                       maj_stat, min_stat, &krb5oid);
284 +               return -1;
285 +       }
286 +
287 +       /*
288 +        * If we failed for any reason to produce global
289 +        * list of supported enctypes, use local default here.
290 +        */
291 +       if (krb5_enctypes == NULL)
292 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
293 +                                       &krb5oid, num_enctypes, &enctypes);
294 +       else
295 +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
296 +                                       &krb5oid, num_krb5_enctypes,
297 +                                       krb5_enctypes);
298 +       if (maj_stat != GSS_S_COMPLETE) {
299 +               pgsserr("gss_set_allowable_enctypes",
300 +                       maj_stat, min_stat, &krb5oid);
301 +               return -1;
302 +       }
303 +       sec->cred = credh;
304 +
305 +       return 0;
306 +}
307 +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
308 +
309 +/*
310 + * Obtain supported enctypes from kernel.
311 + * Set defaults if info is not available.
312 + */
313 +void
314 +gssd_obtain_kernel_krb5_info(void)
315 +{
316 +       char enctype_file_name[128];
317 +       char buf[1024];
318 +       char enctypes[128];
319 +       char extrainfo[1024];
320 +       int fd;
321 +       int use_default_enctypes = 0;
322 +       int nbytes, numfields;
323 +       char default_enctypes[] = "1,3,2";
324 +       int code;
325 +
326 +       snprintf(enctype_file_name, sizeof(enctype_file_name),
327 +                "%s/%s", pipefsdir, "krb5_info");
328 +
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;
336 +               goto do_the_parse;
337 +       }
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;
344 +               goto do_the_parse;
345 +       }
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;
353 +               goto do_the_parse;
354 +       }
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;
360 +               goto do_the_parse;
361 +       }
362 +  do_the_parse:
363 +       if (use_default_enctypes)
364 +               strcpy(enctypes, default_enctypes);
365 +
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)" : "",
370 +                        code);
371 +       }
372 +}
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);
381 +
382  
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
388 @@ -32,6 +32,7 @@
389  #include <stdio.h>
390  #include <syslog.h>
391  #include <string.h>
392 +#include <errno.h>
393  #include <gssapi.h>
394  #include <rpc/rpc.h>
395  #include <rpc/auth_gss.h>
396 @@ -43,9 +44,53 @@
397  #ifdef HAVE_KRB5
398  #include <krb5.h>
399  
400 +/* for 3DES */
401 +#define KG_USAGE_SEAL 22
402 +#define KG_USAGE_SIGN 23
403 +#define KG_USAGE_SEQ  24
404 +
405 +/* for rfc???? */
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
410 +
411 +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
412 +enum seal_alg {
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
418 +};
419 +
420 +#define KEY_USAGE_SEED_ENCRYPTION      0xAA
421 +#define KEY_USAGE_SEED_INTEGRITY       0x55
422 +#define KEY_USAGE_SEED_CHECKSUM                0x99
423 +#define K5CLENGTH 5
424 +
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
429 +
430 +/*
431 + * XXX Hack alert.  We don't have "legal" access to these
432 + * structures located in libk5crypto
433 + */
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();
439 +
440 +void *get_enc_provider();
441 +
442  /* XXX spkm3 seems to actually want it this big, yipes. */
443  #define MAX_CTX_LEN 4096
444  
445 +
446 +
447  #ifdef HAVE_LUCID_CONTEXT_SUPPORT
448  
449  /* Don't use the private structure, use the exported lucid structure */
450 @@ -144,6 +189,96 @@ write_lucid_keyblock(char **p, char *end
451         return 0;
452  }
453  
454 +static void
455 +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
456 +{
457 +       memset(kout, '\0', sizeof(kout));
458 +       kout->enctype = lin->type;
459 +       kout->length = lin->length;
460 +       kout->contents = lin->data;
461 +}
462 +
463 +static void
464 +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
465 +{
466 +       memset(lout, '\0', sizeof(lout));
467 +       lout->type = kin->enctype;
468 +       lout->length = kin->length;
469 +       lout->data = kin->contents;
470 +}
471 +
472 +/*
473 + * Function to derive a new key from a given key and given constant data.
474 + */
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)
478 +{
479 +       krb5_error_code code;
480 +       unsigned char constant_data[K5CLENGTH];
481 +       krb5_data datain;
482 +       int keylength;
483 +       void *enc;
484 +       krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
485 +
486 +       /*
487 +        * XXX Hack alert.  We don't have "legal" access to these
488 +        * values and structures located in libk5crypto
489 +        */
490 +       switch (in->type) {
491 +       case ENCTYPE_DES3_CBC_RAW:
492 +               keylength = 24;
493 +               enc = &krb5int_enc_des3;
494 +               break;
495 +       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
496 +               keylength = 16;
497 +               enc = &krb5int_enc_aes128;
498 +               break;
499 +       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
500 +               keylength = 32;
501 +               enc = &krb5int_enc_aes256;
502 +               break;
503 +       default:
504 +               code = KRB5_BAD_ENCTYPE;
505 +               goto out;
506 +       }
507 +
508 +       /* allocate memory for output key */
509 +       if ((out->data = malloc(keylength)) == NULL) {
510 +               code = ENOMEM;
511 +               goto out;
512 +       }
513 +       out->length = keylength;
514 +       out->type = in->type;
515 +
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);
519 +
520 +       datain.data = (char *) constant_data;
521 +       datain.length = K5CLENGTH;
522 +
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;
527 +
528 +       datain.data[4] = (char) extra;
529 +
530 +       if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) {
531 +               free(out->data);
532 +               out->data = NULL;
533 +               goto out;
534 +       }
535 +       key_krb5_to_lucid(&kout, out);
536 +
537 +  out:
538 +       if (code)
539 +               printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n",
540 +                        code, error_message(code));
541 +       return (code);
542 +}
543 +
544  static int
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;
553  
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
557         return 0;
558  out_err:
559         printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
560 -       if (buf->value) free(buf->value);
561 +       if (buf->value) {
562 +               free(buf->value);
563 +               buf->value = NULL;
564 +       }
565         buf->length = 0;
566 -       if (enc_key.data) free(enc_key.data);
567 +       if (enc_key.data) {
568 +               free(enc_key.data);
569 +               enc_key.data = NULL;
570 +       }
571         return -1;
572  }
573  
574 +/*
575 + * Prepare a new-style buffer to send to the kernel for newer encryption
576 + * types -- or for DES3.
577 + *
578 + * The new format is:
579 + *
580 + *     u32 version;          This is two (2)
581 + *     s32 endtime;
582 + *     u32 flags;
583 + *     #define KRB5_CTX_FLAG_INITIATOR         0x00000001
584 + *     #define KRB5_CTX_FLAG_CFX               0x00000002
585 + *     #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
586 + *     u64 seq_send;
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 )
593 + *
594 + */
595  static int
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)
599  {
600 -       printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
601 +       char *p, *end;
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;
607 +       uint32_t enctype;
608 +       uint32_t keysize;
609 +       uint32_t numkeys;
610 +
611 +       memset(&enc_key, 0, sizeof(enc_key));
612 +       memset(&fakeoid, 0, sizeof(fakeoid));
613 +
614 +       if (!(buf->value = calloc(1, MAX_CTX_LEN)))
615 +               goto out_err;
616 +       p = buf->value;
617 +       end = buf->value + MAX_CTX_LEN;
618 +
619 +       /* Version 2 */
620 +       if (WRITE_BYTES(&p, end , version)) goto out_err;
621 +       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
622 +
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;
629 +
630 +       if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
631 +
632 +       if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
633 +
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? */
639 +       } else {
640 +               if (lctx->cfx_kd.have_acceptor_subkey) {
641 +                       enctype = lctx->cfx_kd.acceptor_subkey.type;
642 +                       keysize = lctx->cfx_kd.acceptor_subkey.length;
643 +               } else {
644 +                       enctype = lctx->cfx_kd.ctx_key.type;
645 +                       keysize = lctx->cfx_kd.ctx_key.length;
646 +               }
647 +               numkeys = 3;
648 +       }
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;
654 +
655 +       if (lctx->protocol == 0) {
656 +               /* derive and send down: Ke, Ki, and Kc */
657 +               /* Ke */
658 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
659 +                               lctx->rfc1964_kd.ctx_key.length))
660 +                       goto out_err;
661 +
662 +               /* Ki */
663 +               if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
664 +                               lctx->rfc1964_kd.ctx_key.length))
665 +                       goto out_err;
666 +
667 +               /* Kc */
668 +               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
669 +                               &derived_key,
670 +                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
671 +                       goto out_err;
672 +               if (write_bytes(&p, end, derived_key.data,
673 +                               derived_key.length))
674 +                       goto out_err;
675 +               free(derived_key.data);
676 +       } else {
677 +               gss_krb5_lucid_key_t *keyptr;
678 +               uint32_t sign_usage, seal_usage;
679 +
680 +               if (lctx->cfx_kd.have_acceptor_subkey)
681 +                       keyptr = &lctx->cfx_kd.acceptor_subkey;
682 +               else
683 +                       keyptr = &lctx->cfx_kd.ctx_key;
684 +
685 +               if (lctx->initiate == 1) {
686 +                       sign_usage = KG_USAGE_INITIATOR_SIGN;
687 +                       seal_usage = KG_USAGE_INITIATOR_SEAL;
688 +               } else {
689 +                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
690 +                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
691 +               }
692 +
693 +               /* derive and send down: Ke, Ki, and Kc */
694 +
695 +               /* Ke */
696 +               if (derive_key_lucid(keyptr, &derived_key,
697 +                              seal_usage, KEY_USAGE_SEED_ENCRYPTION))
698 +                       goto out_err;
699 +               if (write_bytes(&p, end, derived_key.data,
700 +                               derived_key.length))
701 +                       goto out_err;
702 +               free(derived_key.data);
703 +
704 +               /* Ki */
705 +               if (derive_key_lucid(keyptr, &derived_key,
706 +                              seal_usage, KEY_USAGE_SEED_INTEGRITY))
707 +                       goto out_err;
708 +               if (write_bytes(&p, end, derived_key.data,
709 +                               derived_key.length))
710 +                       goto out_err;
711 +               free(derived_key.data);
712 +
713 +               /* Kc */
714 +               if (derive_key_lucid(keyptr, &derived_key,
715 +                              sign_usage, KEY_USAGE_SEED_CHECKSUM))
716 +                       goto out_err;
717 +               if (write_bytes(&p, end, derived_key.data,
718 +                               derived_key.length))
719 +                       goto out_err;
720 +               free(derived_key.data);
721 +       }
722 +
723 +       buf->length = p - (char *)buf->value;
724 +       return 0;
725 +
726 +out_err:
727 +       printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: "
728 +                "failed serializing krb5 context for kernel\n");
729 +       if (buf->value) {
730 +               free(buf->value);
731 +               buf->value = NULL;
732 +       }
733 +       buf->length = 0;
734 +       if (enc_key.data) {
735 +               free(enc_key.data);
736 +               enc_key.data = NULL;
737 +       }
738         return -1;
739  }
740  
741 @@ -258,11 +556,21 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
742                 break;
743         }
744  
745 -       /* Now lctx points to a lucid context that we can send down to kernel */
746 -       if (lctx->protocol == 0)
747 +       /*
748 +        * Now lctx points to a lucid context that we can send down to kernel
749 +        *
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.
755 +        */
756 +
757 +       if (lctx->protocol == 0 &&
758 +               lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW)
759                 retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
760         else
761 -               retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
762 +               retcode = prepare_krb5_ctx_v2_buffer(lctx, buf);
763  
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
767  }
768  
769  /*
770 + * Function to derive a new key from a given key and given constant data.
771 + */
772 +static krb5_error_code
773 +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
774 +{
775 +       krb5_error_code code;
776 +       unsigned char constant_data[K5CLENGTH];
777 +       krb5_data datain;
778 +       int keylength;
779 +       void *enc;
780 +
781 +       /*
782 +        * XXX Hack alert.  We don't have "legal" access to these
783 +        * values and structures located in libk5crypto
784 +        */
785 +       switch (in->enctype) {
786 +       case ENCTYPE_DES3_CBC_RAW:
787 +               keylength = 24;
788 +               enc = &krb5int_enc_des3;
789 +               break;
790 +       case ENCTYPE_ARCFOUR_HMAC:
791 +               keylength = 16;
792 +               enc = &krb5int_enc_arcfour;
793 +               break;
794 +       default:
795 +               code = KRB5_BAD_ENCTYPE;
796 +               goto out;
797 +       }
798 +
799 +       /* allocate memory for output key */
800 +       if ((out->contents = malloc(keylength)) == NULL) {
801 +               code = ENOMEM;
802 +               goto out;
803 +       }
804 +       out->length = keylength;
805 +       out->enctype = in->enctype;
806 +
807 +       datain.data = (char *) constant_data;
808 +       datain.length = K5CLENGTH;
809 +
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;
814 +
815 +       datain.data[4] = (char) extra;
816 +
817 +       if ((code = krb5_derive_key(enc, in, out, &datain))) {
818 +               free(out->contents);
819 +               out->contents = NULL;
820 +       }
821 +
822 +  out:
823 +       if (code)
824 +               printerr(0, "ERROR: derive_key returning error %d (%s)\n",
825 +                        code, error_message(code));
826 +       return (code);
827 +}
828 +
829 +/*
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
834  {
835         krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
836         char *p, *end;
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;
845 +       uint32_t numkeys;
846  
847         if (!(buf->value = calloc(1, MAX_CTX_LEN)))
848                 goto out_err;
849         p = buf->value;
850         end = buf->value + MAX_CTX_LEN;
851  
852 -       if (kctx->initiate) {
853 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
854 -       }
855 -       else {
856 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
857 -       }
858 -       if (kctx->seed_init) {
859 -               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
860 -       }
861 -       else {
862 -               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
863 -       }
864 -       if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
865 -               goto out_err;
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;
872 -
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) {
877 +       case SEAL_ALG_DES:
878 +               /* Versions 0 and 1 */
879 +               if (kctx->initiate) {
880 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
881 +               }
882 +               else {
883 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
884 +               }
885 +               if (kctx->seed_init) {
886 +                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
887 +               }
888 +               else {
889 +                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
890 +               }
891 +               if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
892 +                       goto out_err;
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;
899 +
900 +               printerr(2, "serialize_krb5_ctx: serializing keys with "
901 +                        "enctype %d and length %d\n",
902 +                        kctx->enc->enctype, kctx->enc->length);
903  
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;
908 +               break;
909 +       case SEAL_ALG_MICROSOFT_RC4:
910 +       case SEAL_ALG_DES3KD:
911 +               /* u32 version;   ( 2 )
912 +                * s32 endtime;
913 +                * u32 flags;
914 +                * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
915 +                * #define KRB5_CTX_FLAG_CFX              0x00000002
916 +                * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
917 +                * u64 seq_send;
918 +                * u32  enctype;
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) )
924 +                */
925 +                /* Version 2 */
926 +               if (WRITE_BYTES(&p, end , constant_two)) goto out_err;
927 +               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
928 +
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;
932 +
933 +               seq_send_64bit = kctx->seq_send;
934 +               if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
935 +
936 +               if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
937 +               if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
938 +               numkeys = 3;
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);
943 +
944 +               /* Ke */
945 +               if (write_bytes(&p, end, kctx->enc->contents,
946 +                               kctx->enc->length))
947 +                       goto out_err;
948 +
949 +               /* Ki */
950 +               if (write_bytes(&p, end, kctx->enc->contents,
951 +                               kctx->enc->length))
952 +                       goto out_err;
953 +
954 +               /* Kc */
955 +               if (derive_key(kctx->seq, &derived_key,
956 +                              KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
957 +                       goto out_err;
958 +               if (write_bytes(&p, end, derived_key.contents,
959 +                               derived_key.length))
960 +                       goto out_err;
961 +               free(derived_key.contents);
962 +               break;
963 +       default:
964 +               printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
965 +                        "algorithm %d\n", kctx->sealalg);
966 +               goto out_err;
967 +       }
968  
969         buf->length = p - (char *)buf->value;
970         return 0;
971 +
972  out_err:
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
979         return 0;
980  }
981  
982 +inline static int
983 +write_oid(char **p, char *end, gss_OID_desc *arg)
984 +{
985 +       int len = (int)arg->length;             /* make an int out of size_t */
986 +       if (WRITE_BYTES(p, end, len))
987 +               return -1;
988 +       if (*p + arg->length > end)
989 +               return -1;
990 +       memcpy(*p, arg->elements, len);
991 +       *p += len;
992 +       return 0;
993 +}
994 +
995  static inline int
996  get_bytes(char **ptr, const char *end, void *res, int len)
997  {
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);
1004         if (res < 0) {
1005 -               printerr(0, "WARNING: get_ids: unable to map "
1006 -                       "name '%s' to a uid\n", sname);
1007 +               /*
1008 +                * -ENOENT means there was no mapping, any other error
1009 +                * value means there was an error trying to do the
1010 +                * mapping.
1011 +                */
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;
1017 +                       res = 0;
1018 +                       goto out_free;
1019 +               }
1020 +               printerr(0, "WARNING: get_ids: failed to map name '%s' "
1021 +                       "to uid/gid: %s\n", sname, strerror(-res));
1022                 goto out_free;
1023         }
1024         cred->cr_uid = uid;
1025
1026 _
This page took 0.128914 seconds and 3 git commands to generate.