]>
Commit | Line | Data |
---|---|---|
3df43b59 | 1 | |
2 | ||
3 | The complete set of CITI nfs-utils patches rolled into one patch. | |
4 | ||
5 | Changes since 1.0.8-CITI_NFS4_ALL-1: | |
6 | ||
7 | * Modify the printerr() function to: | |
8 | - be more efficient | |
9 | - use a single buffer rather than two | |
10 | - not completely toss messages that are too long | |
11 | - stop printing messages to syslog DEBUG level | |
12 | ||
13 | * Change the default buffer size in readline function. We are | |
14 | passing much larger messages than it was written to expect. | |
15 | This saves many calls to realloc() to resize the buffer. | |
16 | ||
17 | * Use the correct definition of mech_used in the gss context and use | |
18 | a u_int rather than size_t in calculations. These fix problems on | |
19 | 64-bit big-endian machines. | |
20 | ||
21 | ||
22 | --- | |
23 | ||
24 | nfs-utils-1.0.8-kwc/utils/gssd/cacheio.c | 18 | |
25 | nfs-utils-1.0.8-kwc/utils/gssd/context_mit.c | 511 ++++++++++++++++++++++++-- | |
26 | nfs-utils-1.0.8-kwc/utils/gssd/err_util.c | 61 +-- | |
27 | nfs-utils-1.0.8-kwc/utils/gssd/gss_util.c | 25 + | |
28 | nfs-utils-1.0.8-kwc/utils/gssd/gss_util.h | 1 | |
29 | nfs-utils-1.0.8-kwc/utils/gssd/gssd.c | 5 | |
30 | nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.c | 221 ++++++++--- | |
31 | nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.h | 2 | |
32 | nfs-utils-1.0.8-kwc/utils/gssd/svcgssd.c | 5 | |
33 | nfs-utils-1.0.8-kwc/utils/gssd/svcgssd_proc.c | 19 | |
34 | nfs-utils-1.0.8-kwc/utils/gssd/write_bytes.h | 15 | |
35 | 11 files changed, 761 insertions(+), 122 deletions(-) | |
36 | ||
37 | diff -puN utils/gssd/err_util.c~CITI_NFS4_ALL utils/gssd/err_util.c | |
38 | --- nfs-utils-1.0.8/utils/gssd/err_util.c~CITI_NFS4_ALL 2006-05-26 11:03:04.202437000 -0400 | |
39 | +++ nfs-utils-1.0.8-kwc/utils/gssd/err_util.c 2006-05-26 11:03:04.293437000 -0400 | |
40 | @@ -38,7 +38,6 @@ static int verbosity = 0; | |
41 | static int fg = 0; | |
42 | ||
43 | static char message_buf[500]; | |
44 | -static char tmp_buf[500]; | |
45 | ||
46 | void initerr(char *progname, int set_verbosity, int set_fg) | |
47 | { | |
48 | @@ -48,45 +47,47 @@ void initerr(char *progname, int set_ver | |
49 | openlog(progname, LOG_PID, LOG_DAEMON); | |
50 | } | |
51 | ||
52 | + | |
53 | void printerr(int priority, char *format, ...) | |
54 | { | |
55 | va_list args; | |
56 | int ret; | |
57 | + int buf_used, buf_available; | |
58 | + char *buf; | |
59 | + | |
60 | + /* Don't bother formatting a message we're never going to print! */ | |
61 | + if (priority > verbosity) | |
62 | + return; | |
63 | + | |
64 | + buf_used = strlen(message_buf); | |
65 | + /* subtract 4 to leave room for "...\n" if necessary */ | |
66 | + buf_available = sizeof(message_buf) - buf_used - 4; | |
67 | + buf = message_buf + buf_used; | |
68 | ||
69 | - /* aggregate lines: only print buffer when we get to the end of a | |
70 | - * line or run out of space: */ | |
71 | + /* | |
72 | + * Aggregate lines: only print buffer when we get to the | |
73 | + * end of a line or run out of space | |
74 | + */ | |
75 | va_start(args, format); | |
76 | - ret = vsnprintf(tmp_buf, sizeof(tmp_buf), format, args); | |
77 | + ret = vsnprintf(buf, buf_available, format, args); | |
78 | va_end(args); | |
79 | - if ((ret < 0) || (ret >= sizeof(tmp_buf))) | |
80 | - goto output; | |
81 | - if (strlen(tmp_buf) + strlen(message_buf) + 1 > sizeof(message_buf)) | |
82 | - goto output; | |
83 | - strcat(message_buf, tmp_buf); | |
84 | - if (tmp_buf[strlen(tmp_buf) - 1] == '\n') | |
85 | - goto output; | |
86 | + | |
87 | + if (ret < 0) | |
88 | + goto printit; | |
89 | + if (ret >= buf_available) { | |
90 | + /* Indicate we're truncating */ | |
91 | + strcat(message_buf, "...\n"); | |
92 | + goto printit; | |
93 | + } | |
94 | + if (message_buf[strlen(message_buf) - 1] == '\n') | |
95 | + goto printit; | |
96 | return; | |
97 | -output: | |
98 | - priority -= verbosity; | |
99 | - if (priority < 0) | |
100 | - priority = 0; | |
101 | +printit: | |
102 | if (fg) { | |
103 | - if (priority == 0) | |
104 | - fprintf(stderr, "%s", message_buf); | |
105 | + fprintf(stderr, "%s", message_buf); | |
106 | } else { | |
107 | - int sys_pri; | |
108 | - switch (priority) { | |
109 | - case 0: | |
110 | - sys_pri = LOG_ERR; | |
111 | - break; | |
112 | - case 1: | |
113 | - sys_pri = LOG_DEBUG; | |
114 | - break; | |
115 | - default: | |
116 | - goto out; | |
117 | - } | |
118 | - syslog(sys_pri, "%s", message_buf); | |
119 | + syslog(LOG_ERR, "%s", message_buf); | |
120 | } | |
121 | -out: | |
122 | + /* reset the buffer */ | |
123 | memset(message_buf, 0, sizeof(message_buf)); | |
124 | } | |
125 | diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c | |
126 | --- nfs-utils-1.0.8/utils/gssd/gssd.c~CITI_NFS4_ALL 2006-05-26 11:03:05.185986000 -0400 | |
127 | +++ nfs-utils-1.0.8-kwc/utils/gssd/gssd.c 2006-05-26 11:03:12.251831000 -0400 | |
128 | @@ -145,6 +145,9 @@ main(int argc, char *argv[]) | |
129 | "support setting debug level\n"); | |
130 | #endif | |
131 | ||
132 | + if (gssd_check_mechs() != 0) | |
133 | + errx(1, "Problem with gssapi library"); | |
134 | + | |
135 | if (!fg && daemon(0, 0) < 0) | |
136 | errx(1, "fork"); | |
137 | ||
138 | @@ -154,6 +157,8 @@ main(int argc, char *argv[]) | |
139 | ||
140 | /* Process keytab file and get machine credentials */ | |
141 | gssd_refresh_krb5_machine_creds(); | |
142 | + /* Determine Kerberos information from the kernel */ | |
143 | + gssd_obtain_kernel_krb5_info(); | |
144 | ||
145 | gssd_run(); | |
146 | printerr(0, "gssd_run returned!\n"); | |
147 | diff -puN utils/gssd/gss_util.c~CITI_NFS4_ALL utils/gssd/gss_util.c | |
148 | --- nfs-utils-1.0.8/utils/gssd/gss_util.c~CITI_NFS4_ALL 2006-05-26 11:03:06.223535000 -0400 | |
149 | +++ nfs-utils-1.0.8-kwc/utils/gssd/gss_util.c 2006-05-26 11:03:09.526142000 -0400 | |
150 | @@ -224,3 +224,28 @@ gssd_acquire_cred(char *server_name) | |
151 | ||
152 | return (maj_stat == GSS_S_COMPLETE); | |
153 | } | |
154 | + | |
155 | +int gssd_check_mechs(void) | |
156 | +{ | |
157 | + u_int32_t maj_stat, min_stat; | |
158 | + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; | |
159 | + int retval = -1; | |
160 | + | |
161 | + maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs); | |
162 | + if (maj_stat != GSS_S_COMPLETE) { | |
163 | + printerr(0, "Unable to obtain list of supported mechanisms. " | |
164 | + "Check that gss library is properly configured.\n"); | |
165 | + goto out; | |
166 | + } | |
167 | + if (supported_mechs == GSS_C_NO_OID_SET || | |
168 | + supported_mechs->count == 0) { | |
169 | + printerr(0, "Unable to obtain list of supported mechanisms. " | |
170 | + "Check that gss library is properly configured.\n"); | |
171 | + goto out; | |
172 | + } | |
173 | + maj_stat = gss_release_oid_set(&min_stat, &supported_mechs); | |
174 | + retval = 0; | |
175 | +out: | |
176 | + return retval; | |
177 | +} | |
178 | + | |
179 | diff -puN utils/gssd/gss_util.h~CITI_NFS4_ALL utils/gssd/gss_util.h | |
180 | --- nfs-utils-1.0.8/utils/gssd/gss_util.h~CITI_NFS4_ALL 2006-05-26 11:03:07.460084000 -0400 | |
181 | +++ nfs-utils-1.0.8-kwc/utils/gssd/gss_util.h 2006-05-26 11:03:09.576071000 -0400 | |
182 | @@ -40,5 +40,6 @@ extern gss_cred_id_t gssd_creds; | |
183 | int gssd_acquire_cred(char *server_name); | |
184 | void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, | |
185 | const gss_OID mech); | |
186 | +int gssd_check_mechs(void); | |
187 | ||
188 | #endif /* _GSS_UTIL_H_ */ | |
189 | diff -puN utils/gssd/svcgssd.c~CITI_NFS4_ALL utils/gssd/svcgssd.c | |
190 | --- nfs-utils-1.0.8/utils/gssd/svcgssd.c~CITI_NFS4_ALL 2006-05-26 11:03:07.760787000 -0400 | |
191 | +++ nfs-utils-1.0.8-kwc/utils/gssd/svcgssd.c 2006-05-26 11:03:09.641006000 -0400 | |
192 | @@ -204,6 +204,11 @@ main(int argc, char *argv[]) | |
193 | "support setting debug level\n"); | |
194 | #endif | |
195 | ||
196 | + if (gssd_check_mechs() != 0) { | |
197 | + printerr(0, "ERROR: Problem with gssapi library\n"); | |
198 | + exit(1); | |
199 | + } | |
200 | + | |
201 | if (!fg) | |
202 | mydaemon(0, 0); | |
203 | ||
204 | diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c | |
205 | --- nfs-utils-1.0.8/utils/gssd/krb5_util.c~CITI_NFS4_ALL 2006-05-26 11:03:10.902294000 -0400 | |
206 | +++ nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.c 2006-05-26 11:03:12.451829000 -0400 | |
207 | @@ -97,6 +97,7 @@ | |
208 | #include "config.h" | |
209 | #include <sys/param.h> | |
210 | #include <rpc/rpc.h> | |
211 | +#include <sys/types.h> | |
212 | #include <sys/stat.h> | |
213 | #include <sys/socket.h> | |
214 | #include <arpa/inet.h> | |
215 | @@ -105,6 +106,7 @@ | |
216 | #include <stdlib.h> | |
217 | #include <string.h> | |
218 | #include <dirent.h> | |
219 | +#include <fcntl.h> | |
220 | #include <errno.h> | |
221 | #include <time.h> | |
222 | #include <gssapi/gssapi.h> | |
223 | @@ -123,6 +125,10 @@ | |
224 | /* Global list of principals/cache file names for machine credentials */ | |
225 | struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL; | |
226 | ||
227 | +/* Encryption types supported by the kernel rpcsec_gss code */ | |
228 | +int num_krb5_enctypes = 0; | |
229 | +krb5_enctype *krb5_enctypes = NULL; | |
230 | + | |
231 | /*==========================*/ | |
232 | /*=== Internal routines ===*/ | |
233 | /*==========================*/ | |
234 | @@ -261,51 +267,6 @@ gssd_find_existing_krb5_ccache(uid_t uid | |
235 | } | |
236 | ||
237 | ||
238 | -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
239 | -/* | |
240 | - * this routine obtains a credentials handle via gss_acquire_cred() | |
241 | - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption | |
242 | - * types negotiated. | |
243 | - * | |
244 | - * XXX Should call some function to determine the enctypes supported | |
245 | - * by the kernel. (Only need to do that once!) | |
246 | - * | |
247 | - * Returns: | |
248 | - * 0 => all went well | |
249 | - * -1 => there was an error | |
250 | - */ | |
251 | - | |
252 | -int | |
253 | -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) | |
254 | -{ | |
255 | - u_int maj_stat, min_stat; | |
256 | - gss_cred_id_t credh; | |
257 | - krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC }; | |
258 | - int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); | |
259 | - | |
260 | - maj_stat = gss_acquire_cred(&min_stat, NULL, 0, | |
261 | - GSS_C_NULL_OID_SET, GSS_C_INITIATE, | |
262 | - &credh, NULL, NULL); | |
263 | - | |
264 | - if (maj_stat != GSS_S_COMPLETE) { | |
265 | - pgsserr("gss_acquire_cred", | |
266 | - maj_stat, min_stat, &krb5oid); | |
267 | - return -1; | |
268 | - } | |
269 | - | |
270 | - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid, | |
271 | - num_enctypes, &enctypes); | |
272 | - if (maj_stat != GSS_S_COMPLETE) { | |
273 | - pgsserr("gss_set_allowable_enctypes", | |
274 | - maj_stat, min_stat, &krb5oid); | |
275 | - return -1; | |
276 | - } | |
277 | - sec->cred = credh; | |
278 | - | |
279 | - return 0; | |
280 | -} | |
281 | -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ | |
282 | - | |
283 | /* | |
284 | * Obtain credentials via a key in the keytab given | |
285 | * a keytab handle and a gssd_k5_kt_princ structure. | |
286 | @@ -603,6 +564,56 @@ gssd_set_krb5_ccache_name(char *ccname) | |
287 | #endif | |
288 | } | |
289 | ||
290 | +/* | |
291 | + * Parse the supported encryption type information | |
292 | + */ | |
293 | +static int | |
294 | +parse_enctypes(char *enctypes) | |
295 | +{ | |
296 | + int n = 0; | |
297 | + char *curr, *comma; | |
298 | + int i; | |
299 | + | |
300 | + /* Just in case this ever gets called more than once */ | |
301 | + if (krb5_enctypes != NULL) { | |
302 | + free(krb5_enctypes); | |
303 | + krb5_enctypes = NULL; | |
304 | + num_krb5_enctypes = 0; | |
305 | + } | |
306 | + | |
307 | + /* count the number of commas */ | |
308 | + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) { | |
309 | + comma = strchr(curr, ','); | |
310 | + if (comma != NULL) | |
311 | + n++; | |
312 | + else | |
313 | + break; | |
314 | + } | |
315 | + /* If no more commas and we're not at the end, there's one more value */ | |
316 | + if (*curr != '\0') | |
317 | + n++; | |
318 | + | |
319 | + /* Empty string, return an error */ | |
320 | + if (n == 0) | |
321 | + return ENOENT; | |
322 | + | |
323 | + /* Allocate space for enctypes array */ | |
324 | + if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) { | |
325 | + return ENOMEM; | |
326 | + } | |
327 | + | |
328 | + /* Now parse each value into the array */ | |
329 | + for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) { | |
330 | + krb5_enctypes[i++] = atoi(curr); | |
331 | + comma = strchr(curr, ','); | |
332 | + if (comma == NULL) | |
333 | + break; | |
334 | + } | |
335 | + | |
336 | + num_krb5_enctypes = n; | |
337 | + return 0; | |
338 | +} | |
339 | + | |
340 | /*==========================*/ | |
341 | /*=== External routines ===*/ | |
342 | /*==========================*/ | |
343 | @@ -854,3 +865,123 @@ gssd_destroy_krb5_machine_creds(void) | |
344 | krb5_free_context(context); | |
345 | } | |
346 | ||
347 | +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
348 | +/* | |
349 | + * this routine obtains a credentials handle via gss_acquire_cred() | |
350 | + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption | |
351 | + * types negotiated. | |
352 | + * | |
353 | + * Returns: | |
354 | + * 0 => all went well | |
355 | + * -1 => there was an error | |
356 | + */ | |
357 | + | |
358 | +int | |
359 | +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) | |
360 | +{ | |
361 | + u_int maj_stat, min_stat; | |
362 | + gss_cred_id_t credh; | |
363 | + gss_OID_set_desc desired_mechs; | |
364 | + krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC}; | |
365 | + int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); | |
366 | + | |
367 | + /* We only care about getting a krb5 cred */ | |
368 | + desired_mechs.count = 1; | |
369 | + desired_mechs.elements = &krb5oid; | |
370 | + | |
371 | + maj_stat = gss_acquire_cred(&min_stat, NULL, 0, | |
372 | + &desired_mechs, GSS_C_INITIATE, | |
373 | + &credh, NULL, NULL); | |
374 | + | |
375 | + if (maj_stat != GSS_S_COMPLETE) { | |
376 | + pgsserr("gss_acquire_cred", | |
377 | + maj_stat, min_stat, &krb5oid); | |
378 | + return -1; | |
379 | + } | |
380 | + | |
381 | + /* | |
382 | + * If we failed for any reason to produce global | |
383 | + * list of supported enctypes, use local default here. | |
384 | + */ | |
385 | + if (krb5_enctypes == NULL) | |
386 | + maj_stat = gss_set_allowable_enctypes(&min_stat, credh, | |
387 | + &krb5oid, num_enctypes, &enctypes); | |
388 | + else | |
389 | + maj_stat = gss_set_allowable_enctypes(&min_stat, credh, | |
390 | + &krb5oid, num_krb5_enctypes, | |
391 | + krb5_enctypes); | |
392 | + if (maj_stat != GSS_S_COMPLETE) { | |
393 | + pgsserr("gss_set_allowable_enctypes", | |
394 | + maj_stat, min_stat, &krb5oid); | |
395 | + return -1; | |
396 | + } | |
397 | + sec->cred = credh; | |
398 | + | |
399 | + return 0; | |
400 | +} | |
401 | +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ | |
402 | + | |
403 | +/* | |
404 | + * Obtain supported enctypes from kernel. | |
405 | + * Set defaults if info is not available. | |
406 | + */ | |
407 | +void | |
408 | +gssd_obtain_kernel_krb5_info(void) | |
409 | +{ | |
410 | + char enctype_file_name[128]; | |
411 | + char buf[1024]; | |
412 | + char enctypes[128]; | |
413 | + char extrainfo[1024]; | |
414 | + int fd; | |
415 | + int use_default_enctypes = 0; | |
416 | + int nbytes, numfields; | |
417 | + char default_enctypes[] = "1,3,2"; | |
418 | + int code; | |
419 | + | |
420 | + snprintf(enctype_file_name, sizeof(enctype_file_name), | |
421 | + "%s/%s", pipefsdir, "krb5_info"); | |
422 | + | |
423 | + if ((fd = open(enctype_file_name, O_RDONLY)) == -1) { | |
424 | + printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: " | |
425 | + "Unable to open '%s'. Unable to determine " | |
426 | + "Kerberos encryption types supported by the " | |
427 | + "kernel; using defaults (%s).\n", | |
428 | + enctype_file_name, default_enctypes); | |
429 | + use_default_enctypes = 1; | |
430 | + goto do_the_parse; | |
431 | + } | |
432 | + if ((nbytes = read(fd, buf, sizeof(buf))) == -1) { | |
433 | + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " | |
434 | + "Error reading Kerberos encryption type " | |
435 | + "information file '%s'; using defaults (%s).\n", | |
436 | + enctype_file_name, default_enctypes); | |
437 | + use_default_enctypes = 1; | |
438 | + goto do_the_parse; | |
439 | + } | |
440 | + numfields = sscanf(buf, "enctypes: %s\n%s", enctypes, extrainfo); | |
441 | + if (numfields < 1) { | |
442 | + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " | |
443 | + "error parsing Kerberos encryption type " | |
444 | + "information from file '%s'; using defaults (%s).\n", | |
445 | + enctype_file_name, default_enctypes); | |
446 | + use_default_enctypes = 1; | |
447 | + goto do_the_parse; | |
448 | + } | |
449 | + if (numfields > 1) { | |
450 | + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " | |
451 | + "Extra information, '%s', from '%s' is ignored\n", | |
452 | + enctype_file_name, extrainfo); | |
453 | + use_default_enctypes = 1; | |
454 | + goto do_the_parse; | |
455 | + } | |
456 | + do_the_parse: | |
457 | + if (use_default_enctypes) | |
458 | + strcpy(enctypes, default_enctypes); | |
459 | + | |
460 | + if ((code = parse_enctypes(enctypes)) != 0) { | |
461 | + printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: " | |
462 | + "parse_enctypes%s failed with code %d\n", | |
463 | + use_default_enctypes ? " (with default enctypes)" : "", | |
464 | + code); | |
465 | + } | |
466 | +} | |
467 | diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h | |
468 | --- nfs-utils-1.0.8/utils/gssd/krb5_util.h~CITI_NFS4_ALL 2006-05-26 11:03:12.147829000 -0400 | |
469 | +++ nfs-utils-1.0.8-kwc/utils/gssd/krb5_util.h 2006-05-26 11:03:12.498797000 -0400 | |
470 | @@ -22,6 +22,8 @@ int gssd_refresh_krb5_machine_creds(voi | |
471 | void gssd_free_krb5_machine_cred_list(char **list); | |
472 | void gssd_setup_krb5_machine_gss_ccache(char *servername); | |
473 | void gssd_destroy_krb5_machine_creds(void); | |
474 | +void gssd_obtain_kernel_krb5_info(void); | |
475 | + | |
476 | ||
477 | #ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
478 | int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); | |
479 | diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c | |
480 | --- nfs-utils-1.0.8/utils/gssd/context_mit.c~CITI_NFS4_ALL 2006-05-26 11:03:13.029378000 -0400 | |
481 | +++ nfs-utils-1.0.8-kwc/utils/gssd/context_mit.c 2006-05-26 11:03:14.045927000 -0400 | |
482 | @@ -32,6 +32,7 @@ | |
483 | #include <stdio.h> | |
484 | #include <syslog.h> | |
485 | #include <string.h> | |
486 | +#include <errno.h> | |
487 | #include <gssapi.h> | |
488 | #include <rpc/rpc.h> | |
489 | #include <rpc/auth_gss.h> | |
490 | @@ -43,9 +44,53 @@ | |
491 | #ifdef HAVE_KRB5 | |
492 | #include <krb5.h> | |
493 | ||
494 | +/* for 3DES */ | |
495 | +#define KG_USAGE_SEAL 22 | |
496 | +#define KG_USAGE_SIGN 23 | |
497 | +#define KG_USAGE_SEQ 24 | |
498 | + | |
499 | +/* for rfc???? */ | |
500 | +#define KG_USAGE_ACCEPTOR_SEAL 22 | |
501 | +#define KG_USAGE_ACCEPTOR_SIGN 23 | |
502 | +#define KG_USAGE_INITIATOR_SEAL 24 | |
503 | +#define KG_USAGE_INITIATOR_SIGN 25 | |
504 | + | |
505 | +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */ | |
506 | +enum seal_alg { | |
507 | + SEAL_ALG_NONE = 0xffff, | |
508 | + SEAL_ALG_DES = 0x0000, | |
509 | + SEAL_ALG_1 = 0x0001, /* not published */ | |
510 | + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ | |
511 | + SEAL_ALG_DES3KD = 0x0002 | |
512 | +}; | |
513 | + | |
514 | +#define KEY_USAGE_SEED_ENCRYPTION 0xAA | |
515 | +#define KEY_USAGE_SEED_INTEGRITY 0x55 | |
516 | +#define KEY_USAGE_SEED_CHECKSUM 0x99 | |
517 | +#define K5CLENGTH 5 | |
518 | + | |
519 | +/* Flags for version 2 context flags */ | |
520 | +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
521 | +#define KRB5_CTX_FLAG_CFX 0x00000002 | |
522 | +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
523 | + | |
524 | +/* | |
525 | + * XXX Hack alert. We don't have "legal" access to these | |
526 | + * structures located in libk5crypto | |
527 | + */ | |
528 | +extern void krb5int_enc_arcfour; | |
529 | +extern void krb5int_enc_des3; | |
530 | +extern void krb5int_enc_aes128; | |
531 | +extern void krb5int_enc_aes256; | |
532 | +extern int krb5_derive_key(); | |
533 | + | |
534 | +void *get_enc_provider(); | |
535 | + | |
536 | /* XXX spkm3 seems to actually want it this big, yipes. */ | |
537 | #define MAX_CTX_LEN 4096 | |
538 | ||
539 | + | |
540 | + | |
541 | #ifdef HAVE_LUCID_CONTEXT_SUPPORT | |
542 | ||
543 | /* Don't use the private structure, use the exported lucid structure */ | |
544 | @@ -86,7 +131,7 @@ typedef struct _krb5_gss_ctx_id_rec { | |
545 | uint64_t seq_recv; /* gssint_uint64 */ | |
546 | void *seqstate; | |
547 | krb5_auth_context auth_context; | |
548 | - gss_buffer_desc *mech_used; /* gss_OID_desc */ | |
549 | + gss_OID_desc *mech_used; /* gss_OID_desc */ | |
550 | /* Protocol spec revision | |
551 | 0 => RFC 1964 with 3DES and RC4 enhancements | |
552 | 1 => draft-ietf-krb-wg-gssapi-cfx-01 | |
553 | @@ -123,7 +168,7 @@ typedef struct _krb5_gss_ctx_id_rec { | |
554 | int established; | |
555 | int big_endian; | |
556 | krb5_auth_context auth_context; | |
557 | - gss_buffer_desc *mech_used; | |
558 | + gss_OID_desc *mech_used; | |
559 | int nctypes; | |
560 | krb5_cksumtype *ctypes; | |
561 | } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; | |
562 | @@ -144,6 +189,96 @@ write_lucid_keyblock(char **p, char *end | |
563 | return 0; | |
564 | } | |
565 | ||
566 | +static void | |
567 | +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout) | |
568 | +{ | |
569 | + memset(kout, '\0', sizeof(kout)); | |
570 | + kout->enctype = lin->type; | |
571 | + kout->length = lin->length; | |
572 | + kout->contents = lin->data; | |
573 | +} | |
574 | + | |
575 | +static void | |
576 | +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout) | |
577 | +{ | |
578 | + memset(lout, '\0', sizeof(lout)); | |
579 | + lout->type = kin->enctype; | |
580 | + lout->length = kin->length; | |
581 | + lout->data = kin->contents; | |
582 | +} | |
583 | + | |
584 | +/* | |
585 | + * Function to derive a new key from a given key and given constant data. | |
586 | + */ | |
587 | +static krb5_error_code | |
588 | +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out, | |
589 | + int usage, char extra) | |
590 | +{ | |
591 | + krb5_error_code code; | |
592 | + unsigned char constant_data[K5CLENGTH]; | |
593 | + krb5_data datain; | |
594 | + int keylength; | |
595 | + void *enc; | |
596 | + krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */ | |
597 | + | |
598 | + /* | |
599 | + * XXX Hack alert. We don't have "legal" access to these | |
600 | + * values and structures located in libk5crypto | |
601 | + */ | |
602 | + switch (in->type) { | |
603 | + case ENCTYPE_DES3_CBC_RAW: | |
604 | + keylength = 24; | |
605 | + enc = &krb5int_enc_des3; | |
606 | + break; | |
607 | + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | |
608 | + keylength = 16; | |
609 | + enc = &krb5int_enc_aes128; | |
610 | + break; | |
611 | + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | |
612 | + keylength = 32; | |
613 | + enc = &krb5int_enc_aes256; | |
614 | + break; | |
615 | + default: | |
616 | + code = KRB5_BAD_ENCTYPE; | |
617 | + goto out; | |
618 | + } | |
619 | + | |
620 | + /* allocate memory for output key */ | |
621 | + if ((out->data = malloc(keylength)) == NULL) { | |
622 | + code = ENOMEM; | |
623 | + goto out; | |
624 | + } | |
625 | + out->length = keylength; | |
626 | + out->type = in->type; | |
627 | + | |
628 | + /* Convert to correct format for call to krb5_derive_key */ | |
629 | + key_lucid_to_krb5(in, &kin); | |
630 | + key_lucid_to_krb5(out, &kout); | |
631 | + | |
632 | + datain.data = (char *) constant_data; | |
633 | + datain.length = K5CLENGTH; | |
634 | + | |
635 | + datain.data[0] = (usage>>24)&0xff; | |
636 | + datain.data[1] = (usage>>16)&0xff; | |
637 | + datain.data[2] = (usage>>8)&0xff; | |
638 | + datain.data[3] = usage&0xff; | |
639 | + | |
640 | + datain.data[4] = (char) extra; | |
641 | + | |
642 | + if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) { | |
643 | + free(out->data); | |
644 | + out->data = NULL; | |
645 | + goto out; | |
646 | + } | |
647 | + key_krb5_to_lucid(&kout, out); | |
648 | + | |
649 | + out: | |
650 | + if (code) | |
651 | + printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n", | |
652 | + code, error_message(code)); | |
653 | + return (code); | |
654 | +} | |
655 | + | |
656 | static int | |
657 | prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, | |
658 | gss_buffer_desc *buf) | |
659 | @@ -183,7 +318,7 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc | |
660 | if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; | |
661 | word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */ | |
662 | if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err; | |
663 | - if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err; | |
664 | + if (write_oid(&p, end, &krb5oid)) goto out_err; | |
665 | ||
666 | printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " | |
667 | "enctype %d and length %d\n", | |
668 | @@ -212,17 +347,180 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc | |
669 | return 0; | |
670 | out_err: | |
671 | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); | |
672 | - if (buf->value) free(buf->value); | |
673 | + if (buf->value) { | |
674 | + free(buf->value); | |
675 | + buf->value = NULL; | |
676 | + } | |
677 | buf->length = 0; | |
678 | - if (enc_key.data) free(enc_key.data); | |
679 | + if (enc_key.data) { | |
680 | + free(enc_key.data); | |
681 | + enc_key.data = NULL; | |
682 | + } | |
683 | return -1; | |
684 | } | |
685 | ||
686 | +/* | |
687 | + * Prepare a new-style buffer to send to the kernel for newer encryption | |
688 | + * types -- or for DES3. | |
689 | + * | |
690 | + * The new format is: | |
691 | + * | |
692 | + * u32 version; This is two (2) | |
693 | + * s32 endtime; | |
694 | + * u32 flags; | |
695 | + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
696 | + * #define KRB5_CTX_FLAG_CFX 0x00000002 | |
697 | + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
698 | + * u64 seq_send; | |
699 | + * u32 enctype; ( encrption type of keys ) | |
700 | + * u32 size_of_each_key; ( size of each key in bytes ) | |
701 | + * u32 number_of_keys; ( N -- should always be 3 for now ) | |
702 | + * keydata-1; ( Ke ) | |
703 | + * keydata-2; ( Ki ) | |
704 | + * keydata-3; ( Kc ) | |
705 | + * | |
706 | + */ | |
707 | static int | |
708 | -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx, | |
709 | +prepare_krb5_ctx_v2_buffer(gss_krb5_lucid_context_v1_t *lctx, | |
710 | gss_buffer_desc *buf) | |
711 | { | |
712 | - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n"); | |
713 | + char *p, *end; | |
714 | + static uint32_t version = 2; | |
715 | + uint32_t v2_flags = 0; | |
716 | + gss_krb5_lucid_key_t enc_key; | |
717 | + gss_krb5_lucid_key_t derived_key; | |
718 | + gss_buffer_desc fakeoid; | |
719 | + uint32_t enctype; | |
720 | + uint32_t keysize; | |
721 | + uint32_t numkeys; | |
722 | + | |
723 | + memset(&enc_key, 0, sizeof(enc_key)); | |
724 | + memset(&fakeoid, 0, sizeof(fakeoid)); | |
725 | + | |
726 | + if (!(buf->value = calloc(1, MAX_CTX_LEN))) | |
727 | + goto out_err; | |
728 | + p = buf->value; | |
729 | + end = buf->value + MAX_CTX_LEN; | |
730 | + | |
731 | + /* Version 2 */ | |
732 | + if (WRITE_BYTES(&p, end , version)) goto out_err; | |
733 | + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; | |
734 | + | |
735 | + if (lctx->initiate) | |
736 | + v2_flags |= KRB5_CTX_FLAG_INITIATOR; | |
737 | + if (lctx->protocol != 0) | |
738 | + v2_flags |= KRB5_CTX_FLAG_CFX; | |
739 | + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) | |
740 | + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; | |
741 | + | |
742 | + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; | |
743 | + | |
744 | + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; | |
745 | + | |
746 | + /* Protocol 0 here implies DES3 or RC4 */ | |
747 | + if (lctx->protocol == 0) { | |
748 | + enctype = lctx->rfc1964_kd.ctx_key.type; | |
749 | + keysize = lctx->rfc1964_kd.ctx_key.length; | |
750 | + numkeys = 3; /* XXX is always gonna be three? */ | |
751 | + } else { | |
752 | + if (lctx->cfx_kd.have_acceptor_subkey) { | |
753 | + enctype = lctx->cfx_kd.acceptor_subkey.type; | |
754 | + keysize = lctx->cfx_kd.acceptor_subkey.length; | |
755 | + } else { | |
756 | + enctype = lctx->cfx_kd.ctx_key.type; | |
757 | + keysize = lctx->cfx_kd.ctx_key.length; | |
758 | + } | |
759 | + numkeys = 3; | |
760 | + } | |
761 | + printerr(2, "prepare_krb5_ctx_v2_buffer: serializing %d keys with " | |
762 | + "enctype %d and size %d\n", numkeys, enctype, keysize); | |
763 | + if (WRITE_BYTES(&p, end, enctype)) goto out_err; | |
764 | + if (WRITE_BYTES(&p, end, keysize)) goto out_err; | |
765 | + if (WRITE_BYTES(&p, end, numkeys)) goto out_err; | |
766 | + | |
767 | + if (lctx->protocol == 0) { | |
768 | + /* derive and send down: Ke, Ki, and Kc */ | |
769 | + /* Ke */ | |
770 | + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, | |
771 | + lctx->rfc1964_kd.ctx_key.length)) | |
772 | + goto out_err; | |
773 | + | |
774 | + /* Ki */ | |
775 | + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, | |
776 | + lctx->rfc1964_kd.ctx_key.length)) | |
777 | + goto out_err; | |
778 | + | |
779 | + /* Kc */ | |
780 | + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, | |
781 | + &derived_key, | |
782 | + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) | |
783 | + goto out_err; | |
784 | + if (write_bytes(&p, end, derived_key.data, | |
785 | + derived_key.length)) | |
786 | + goto out_err; | |
787 | + free(derived_key.data); | |
788 | + } else { | |
789 | + gss_krb5_lucid_key_t *keyptr; | |
790 | + uint32_t sign_usage, seal_usage; | |
791 | + | |
792 | + if (lctx->cfx_kd.have_acceptor_subkey) | |
793 | + keyptr = &lctx->cfx_kd.acceptor_subkey; | |
794 | + else | |
795 | + keyptr = &lctx->cfx_kd.ctx_key; | |
796 | + | |
797 | + if (lctx->initiate == 1) { | |
798 | + sign_usage = KG_USAGE_INITIATOR_SIGN; | |
799 | + seal_usage = KG_USAGE_INITIATOR_SEAL; | |
800 | + } else { | |
801 | + sign_usage = KG_USAGE_ACCEPTOR_SIGN; | |
802 | + seal_usage = KG_USAGE_ACCEPTOR_SEAL; | |
803 | + } | |
804 | + | |
805 | + /* derive and send down: Ke, Ki, and Kc */ | |
806 | + | |
807 | + /* Ke */ | |
808 | + if (derive_key_lucid(keyptr, &derived_key, | |
809 | + seal_usage, KEY_USAGE_SEED_ENCRYPTION)) | |
810 | + goto out_err; | |
811 | + if (write_bytes(&p, end, derived_key.data, | |
812 | + derived_key.length)) | |
813 | + goto out_err; | |
814 | + free(derived_key.data); | |
815 | + | |
816 | + /* Ki */ | |
817 | + if (derive_key_lucid(keyptr, &derived_key, | |
818 | + seal_usage, KEY_USAGE_SEED_INTEGRITY)) | |
819 | + goto out_err; | |
820 | + if (write_bytes(&p, end, derived_key.data, | |
821 | + derived_key.length)) | |
822 | + goto out_err; | |
823 | + free(derived_key.data); | |
824 | + | |
825 | + /* Kc */ | |
826 | + if (derive_key_lucid(keyptr, &derived_key, | |
827 | + sign_usage, KEY_USAGE_SEED_CHECKSUM)) | |
828 | + goto out_err; | |
829 | + if (write_bytes(&p, end, derived_key.data, | |
830 | + derived_key.length)) | |
831 | + goto out_err; | |
832 | + free(derived_key.data); | |
833 | + } | |
834 | + | |
835 | + buf->length = p - (char *)buf->value; | |
836 | + return 0; | |
837 | + | |
838 | +out_err: | |
839 | + printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: " | |
840 | + "failed serializing krb5 context for kernel\n"); | |
841 | + if (buf->value) { | |
842 | + free(buf->value); | |
843 | + buf->value = NULL; | |
844 | + } | |
845 | + buf->length = 0; | |
846 | + if (enc_key.data) { | |
847 | + free(enc_key.data); | |
848 | + enc_key.data = NULL; | |
849 | + } | |
850 | return -1; | |
851 | } | |
852 | ||
853 | @@ -258,11 +556,21 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss | |
854 | break; | |
855 | } | |
856 | ||
857 | - /* Now lctx points to a lucid context that we can send down to kernel */ | |
858 | - if (lctx->protocol == 0) | |
859 | + /* | |
860 | + * Now lctx points to a lucid context that we can send down to kernel | |
861 | + * | |
862 | + * Note: we send down different information to the kernel depending | |
863 | + * on the protocol version and the enctyption type. | |
864 | + * For protocol version 0 with all enctypes besides DES3, we use | |
865 | + * the original format. For protocol version != 0 or DES3, we | |
866 | + * send down the new style information. | |
867 | + */ | |
868 | + | |
869 | + if (lctx->protocol == 0 && | |
870 | + lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW) | |
871 | retcode = prepare_krb5_rfc1964_buffer(lctx, buf); | |
872 | else | |
873 | - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf); | |
874 | + retcode = prepare_krb5_ctx_v2_buffer(lctx, buf); | |
875 | ||
876 | maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); | |
877 | if (maj_stat != GSS_S_COMPLETE) { | |
878 | @@ -300,6 +608,66 @@ write_keyblock(char **p, char *end, stru | |
879 | } | |
880 | ||
881 | /* | |
882 | + * Function to derive a new key from a given key and given constant data. | |
883 | + */ | |
884 | +static krb5_error_code | |
885 | +derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra) | |
886 | +{ | |
887 | + krb5_error_code code; | |
888 | + unsigned char constant_data[K5CLENGTH]; | |
889 | + krb5_data datain; | |
890 | + int keylength; | |
891 | + void *enc; | |
892 | + | |
893 | + /* | |
894 | + * XXX Hack alert. We don't have "legal" access to these | |
895 | + * values and structures located in libk5crypto | |
896 | + */ | |
897 | + switch (in->enctype) { | |
898 | + case ENCTYPE_DES3_CBC_RAW: | |
899 | + keylength = 24; | |
900 | + enc = &krb5int_enc_des3; | |
901 | + break; | |
902 | + case ENCTYPE_ARCFOUR_HMAC: | |
903 | + keylength = 16; | |
904 | + enc = &krb5int_enc_arcfour; | |
905 | + break; | |
906 | + default: | |
907 | + code = KRB5_BAD_ENCTYPE; | |
908 | + goto out; | |
909 | + } | |
910 | + | |
911 | + /* allocate memory for output key */ | |
912 | + if ((out->contents = malloc(keylength)) == NULL) { | |
913 | + code = ENOMEM; | |
914 | + goto out; | |
915 | + } | |
916 | + out->length = keylength; | |
917 | + out->enctype = in->enctype; | |
918 | + | |
919 | + datain.data = (char *) constant_data; | |
920 | + datain.length = K5CLENGTH; | |
921 | + | |
922 | + datain.data[0] = (usage>>24)&0xff; | |
923 | + datain.data[1] = (usage>>16)&0xff; | |
924 | + datain.data[2] = (usage>>8)&0xff; | |
925 | + datain.data[3] = usage&0xff; | |
926 | + | |
927 | + datain.data[4] = (char) extra; | |
928 | + | |
929 | + if ((code = krb5_derive_key(enc, in, out, &datain))) { | |
930 | + free(out->contents); | |
931 | + out->contents = NULL; | |
932 | + } | |
933 | + | |
934 | + out: | |
935 | + if (code) | |
936 | + printerr(0, "ERROR: derive_key returning error %d (%s)\n", | |
937 | + code, error_message(code)); | |
938 | + return (code); | |
939 | +} | |
940 | + | |
941 | +/* | |
942 | * We really shouldn't know about glue-layer context structure, but | |
943 | * we need to get at the real krb5 context pointer. This should be | |
944 | * removed as soon as we say there is no support for MIT Kerberos | |
945 | @@ -315,45 +683,114 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss | |
946 | { | |
947 | krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id; | |
948 | char *p, *end; | |
949 | - static int constant_one = 1; | |
950 | static int constant_zero = 0; | |
951 | + static int constant_one = 1; | |
952 | + static int constant_two = 2; | |
953 | uint32_t word_seq_send; | |
954 | + u_int64_t seq_send_64bit; | |
955 | + uint32_t v2_flags = 0; | |
956 | + krb5_keyblock derived_key; | |
957 | + uint32_t numkeys; | |
958 | ||
959 | if (!(buf->value = calloc(1, MAX_CTX_LEN))) | |
960 | goto out_err; | |
961 | p = buf->value; | |
962 | end = buf->value + MAX_CTX_LEN; | |
963 | ||
964 | - if (kctx->initiate) { | |
965 | - if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
966 | - } | |
967 | - else { | |
968 | - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
969 | - } | |
970 | - if (kctx->seed_init) { | |
971 | - if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
972 | - } | |
973 | - else { | |
974 | - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
975 | - } | |
976 | - if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) | |
977 | - goto out_err; | |
978 | - if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; | |
979 | - if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; | |
980 | - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; | |
981 | - word_seq_send = kctx->seq_send; | |
982 | - if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; | |
983 | - if (write_buffer(&p, end, kctx->mech_used)) goto out_err; | |
984 | - | |
985 | - printerr(2, "serialize_krb5_ctx: serializing keys with " | |
986 | - "enctype %d and length %d\n", | |
987 | - kctx->enc->enctype, kctx->enc->length); | |
988 | + switch (kctx->sealalg) { | |
989 | + case SEAL_ALG_DES: | |
990 | + /* Versions 0 and 1 */ | |
991 | + if (kctx->initiate) { | |
992 | + if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
993 | + } | |
994 | + else { | |
995 | + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
996 | + } | |
997 | + if (kctx->seed_init) { | |
998 | + if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
999 | + } | |
1000 | + else { | |
1001 | + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
1002 | + } | |
1003 | + if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) | |
1004 | + goto out_err; | |
1005 | + if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; | |
1006 | + if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; | |
1007 | + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; | |
1008 | + word_seq_send = kctx->seq_send; | |
1009 | + if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; | |
1010 | + if (write_oid(&p, end, kctx->mech_used)) goto out_err; | |
1011 | + | |
1012 | + printerr(2, "serialize_krb5_ctx: serializing keys with " | |
1013 | + "enctype %d and length %d\n", | |
1014 | + kctx->enc->enctype, kctx->enc->length); | |
1015 | ||
1016 | - if (write_keyblock(&p, end, kctx->enc)) goto out_err; | |
1017 | - if (write_keyblock(&p, end, kctx->seq)) goto out_err; | |
1018 | + if (write_keyblock(&p, end, kctx->enc)) goto out_err; | |
1019 | + if (write_keyblock(&p, end, kctx->seq)) goto out_err; | |
1020 | + break; | |
1021 | + case SEAL_ALG_MICROSOFT_RC4: | |
1022 | + case SEAL_ALG_DES3KD: | |
1023 | + /* u32 version; ( 2 ) | |
1024 | + * s32 endtime; | |
1025 | + * u32 flags; | |
1026 | + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
1027 | + * #define KRB5_CTX_FLAG_CFX 0x00000002 | |
1028 | + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
1029 | + * u64 seq_send; | |
1030 | + * u32 enctype; | |
1031 | + * u32 size_of_each_key; ( size in bytes ) | |
1032 | + * u32 number_of_keys; ( N (assumed to be 3 for now) ) | |
1033 | + * keydata-1; ( Ke (Kenc for DES3) ) | |
1034 | + * keydata-2; ( Ki (Kseq for DES3) ) | |
1035 | + * keydata-3; ( Kc (derived checksum key) ) | |
1036 | + */ | |
1037 | + /* Version 2 */ | |
1038 | + if (WRITE_BYTES(&p, end , constant_two)) goto out_err; | |
1039 | + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; | |
1040 | + | |
1041 | + /* Only applicable flag for is initiator */ | |
1042 | + if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR; | |
1043 | + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; | |
1044 | + | |
1045 | + seq_send_64bit = kctx->seq_send; | |
1046 | + if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err; | |
1047 | + | |
1048 | + if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err; | |
1049 | + if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err; | |
1050 | + numkeys = 3; | |
1051 | + if (WRITE_BYTES(&p, end, numkeys)) goto out_err; | |
1052 | + printerr(2, "serialize_krb5_ctx: serializing %d keys with " | |
1053 | + "enctype %d and size %d\n", | |
1054 | + numkeys, kctx->enc->enctype, kctx->enc->length); | |
1055 | + | |
1056 | + /* Ke */ | |
1057 | + if (write_bytes(&p, end, kctx->enc->contents, | |
1058 | + kctx->enc->length)) | |
1059 | + goto out_err; | |
1060 | + | |
1061 | + /* Ki */ | |
1062 | + if (write_bytes(&p, end, kctx->enc->contents, | |
1063 | + kctx->enc->length)) | |
1064 | + goto out_err; | |
1065 | + | |
1066 | + /* Kc */ | |
1067 | + if (derive_key(kctx->seq, &derived_key, | |
1068 | + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) | |
1069 | + goto out_err; | |
1070 | + if (write_bytes(&p, end, derived_key.contents, | |
1071 | + derived_key.length)) | |
1072 | + goto out_err; | |
1073 | + free(derived_key.contents); | |
1074 | + break; | |
1075 | + default: | |
1076 | + printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal " | |
1077 | + "algorithm %d\n", kctx->sealalg); | |
1078 | + goto out_err; | |
1079 | + } | |
1080 | ||
1081 | buf->length = p - (char *)buf->value; | |
1082 | return 0; | |
1083 | + | |
1084 | out_err: | |
1085 | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); | |
1086 | if (buf->value) free(buf->value); | |
1087 | diff -puN utils/gssd/write_bytes.h~CITI_NFS4_ALL utils/gssd/write_bytes.h | |
1088 | --- nfs-utils-1.0.8/utils/gssd/write_bytes.h~CITI_NFS4_ALL 2006-05-26 11:03:13.360378000 -0400 | |
1089 | +++ nfs-utils-1.0.8-kwc/utils/gssd/write_bytes.h 2006-05-26 11:03:13.867977000 -0400 | |
1090 | @@ -56,13 +56,26 @@ write_buffer(char **p, char *end, gss_bu | |
1091 | int len = (int)arg->length; /* make an int out of size_t */ | |
1092 | if (WRITE_BYTES(p, end, len)) | |
1093 | return -1; | |
1094 | - if (*p + arg->length > end) | |
1095 | + if (*p + len > end) | |
1096 | return -1; | |
1097 | memcpy(*p, arg->value, len); | |
1098 | *p += len; | |
1099 | return 0; | |
1100 | } | |
1101 | ||
1102 | +inline static int | |
1103 | +write_oid(char **p, char *end, gss_OID_desc *arg) | |
1104 | +{ | |
1105 | + int len = (int)arg->length; /* make an int out of size_t */ | |
1106 | + if (WRITE_BYTES(p, end, len)) | |
1107 | + return -1; | |
1108 | + if (*p + arg->length > end) | |
1109 | + return -1; | |
1110 | + memcpy(*p, arg->elements, len); | |
1111 | + *p += len; | |
1112 | + return 0; | |
1113 | +} | |
1114 | + | |
1115 | static inline int | |
1116 | get_bytes(char **ptr, const char *end, void *res, int len) | |
1117 | { | |
1118 | diff -puN utils/gssd/cacheio.c~CITI_NFS4_ALL utils/gssd/cacheio.c | |
1119 | --- nfs-utils-1.0.8/utils/gssd/cacheio.c~CITI_NFS4_ALL 2006-05-26 11:03:14.443930000 -0400 | |
1120 | +++ nfs-utils-1.0.8-kwc/utils/gssd/cacheio.c 2006-05-26 11:03:15.616328000 -0400 | |
1121 | @@ -55,6 +55,7 @@ | |
1122 | #include <time.h> | |
1123 | #include <stdlib.h> | |
1124 | #include <string.h> | |
1125 | +#include <errno.h> | |
1126 | #include "err_util.h" | |
1127 | ||
1128 | void qword_add(char **bpp, int *lp, char *str) | |
1129 | @@ -244,6 +245,8 @@ int qword_get_int(char **bpp, int *anint | |
1130 | return 0; | |
1131 | } | |
1132 | ||
1133 | +#define READLINE_BUFFER_INCREMENT 2048 | |
1134 | + | |
1135 | int readline(int fd, char **buf, int *lenp) | |
1136 | { | |
1137 | /* read a line into *buf, which is malloced *len long | |
1138 | @@ -254,15 +257,16 @@ int readline(int fd, char **buf, int *le | |
1139 | int len; | |
1140 | ||
1141 | if (*lenp == 0) { | |
1142 | - char *b = malloc(128); | |
1143 | + char *b = malloc(READLINE_BUFFER_INCREMENT); | |
1144 | if (b == NULL) | |
1145 | return 0; | |
1146 | *buf = b; | |
1147 | - *lenp = 128; | |
1148 | + *lenp = READLINE_BUFFER_INCREMENT; | |
1149 | } | |
1150 | len = read(fd, *buf, *lenp); | |
1151 | if (len <= 0) { | |
1152 | - printerr(2, "read error in readline: %d\n", len); | |
1153 | + printerr(0, "readline: read error: len %d errno %d (%s)\n", | |
1154 | + len, errno, strerror(errno)); | |
1155 | return 0; | |
1156 | } | |
1157 | while ((*buf)[len-1] != '\n') { | |
1158 | @@ -271,19 +275,21 @@ int readline(int fd, char **buf, int *le | |
1159 | */ | |
1160 | char *new; | |
1161 | int nl; | |
1162 | - *lenp += 128; | |
1163 | + *lenp += READLINE_BUFFER_INCREMENT; | |
1164 | new = realloc(*buf, *lenp); | |
1165 | if (new == NULL) | |
1166 | return 0; | |
1167 | *buf = new; | |
1168 | nl = read(fd, *buf +len, *lenp - len); | |
1169 | if (nl <= 0 ) { | |
1170 | - printerr(2, "read error in readline: %d\n", nl); | |
1171 | + printerr(0, "readline: read error: len %d " | |
1172 | + "errno %d (%s)\n", nl, errno, strerror(errno)); | |
1173 | return 0; | |
1174 | } | |
1175 | len += nl; | |
1176 | } | |
1177 | (*buf)[len-1] = 0; | |
1178 | - printerr(1, "read line with %d characters:\n%s\n", *lenp, *buf); | |
1179 | + printerr(3, "readline: read %d chars into buffer of size %d:\n%s\n", | |
1180 | + len, *lenp, *buf); | |
1181 | return 1; | |
1182 | } | |
1183 | diff -puN utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL utils/gssd/svcgssd_proc.c | |
1184 | --- nfs-utils-1.0.8/utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL 2006-05-26 11:03:15.453476000 -0400 | |
1185 | +++ nfs-utils-1.0.8-kwc/utils/gssd/svcgssd_proc.c 2006-05-26 11:03:16.282025000 -0400 | |
1186 | @@ -140,7 +140,7 @@ send_response(FILE *f, gss_buffer_desc * | |
1187 | return -1; | |
1188 | } | |
1189 | *bp = '\0'; | |
1190 | - printerr(1, "writing message: %s", buf); | |
1191 | + printerr(3, "writing message: %s", buf); | |
1192 | if (write(g, buf, bp - buf) == -1) { | |
1193 | printerr(0, "WARNING: failed to write message\n"); | |
1194 | close(g); | |
1195 | @@ -220,8 +220,21 @@ get_ids(gss_name_t client_name, gss_OID | |
1196 | nfs4_init_name_mapping(NULL); /* XXX: should only do this once */ | |
1197 | res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid); | |
1198 | if (res < 0) { | |
1199 | - printerr(0, "WARNING: get_ids: unable to map " | |
1200 | - "name '%s' to a uid\n", sname); | |
1201 | + /* | |
1202 | + * -ENOENT means there was no mapping, any other error | |
1203 | + * value means there was an error trying to do the | |
1204 | + * mapping. | |
1205 | + */ | |
1206 | + if (res == -ENOENT) { | |
1207 | + cred->cr_uid = -2; /* XXX */ | |
1208 | + cred->cr_gid = -2; /* XXX */ | |
1209 | + cred->cr_groups[0] = -2;/* XXX */ | |
1210 | + cred->cr_ngroups = 1; | |
1211 | + res = 0; | |
1212 | + goto out_free; | |
1213 | + } | |
1214 | + printerr(0, "WARNING: get_ids: failed to map name '%s' " | |
1215 | + "to uid/gid: %s\n", sname, strerror(-res)); | |
1216 | goto out_free; | |
1217 | } | |
1218 | cred->cr_uid = uid; | |
1219 | ||
1220 | _ |