]>
Commit | Line | Data |
---|---|---|
97cc26d8 JB |
1 | |
2 | ||
14bcaf3a | 3 | The complete set of CITI nfs-utils patches rolled into one patch. |
97cc26d8 | 4 | |
12480a97 | 5 | Changes since 1.1.1-CITI_NFS4_ALL-1: |
97cc26d8 | 6 | |
12480a97 | 7 | * Update to nfs-utils-1.1.2 |
71f23813 | 8 | |
12480a97 JB |
9 | * Patch from Olga Kornievskaia to read port number from the info |
10 | file to support non-standard ports. | |
71f23813 | 11 | |
12480a97 JB |
12 | * Patch to include the "other" DES encryption types when negotiating |
13 | a context. | |
97cc26d8 | 14 | |
12480a97 JB |
15 | * Patch originally from Vince Busam <vbusam@google.com> to support looking |
16 | in multiple directories for credential caches to use when creating | |
17 | a context. | |
97cc26d8 | 18 | |
12480a97 JB |
19 | * A TEMPORARY patch to read a krb5_info file to determine which |
20 | encryption types the kernel gss_krb5 code supports. | |
21 | ||
22 | * A patch to send down a new context format for encryption types | |
23 | other than DES. | |
97cc26d8 JB |
24 | |
25 | --- | |
26 | ||
12480a97 JB |
27 | utils/gssd/context.h | 6 - |
28 | utils/gssd/context_lucid.c | 132 +++++++++++++++++++--- | |
29 | utils/gssd/context_mit.c | 134 +++++++++++++++++----- | |
30 | utils/gssd/err_util.c | 5 | |
31 | utils/gssd/err_util.h | 1 | |
32 | utils/gssd/gssd.c | 13 ++ | |
33 | utils/gssd/gssd.h | 4 | |
34 | utils/gssd/gssd.man | 6 - | |
35 | utils/gssd/gssd_proc.c | 25 +++- | |
36 | utils/gssd/krb5_util.c | 263 ++++++++++++++++++++++++++++++++++----------- | |
37 | utils/gssd/krb5_util.h | 5 | |
38 | 11 files changed, 473 insertions(+), 121 deletions(-) | |
97cc26d8 | 39 | |
12480a97 JB |
40 | diff -puN utils/gssd/gssd.h~CITI_NFS4_ALL utils/gssd/gssd.h |
41 | --- nfs-utils-1.1.2/utils/gssd/gssd.h~CITI_NFS4_ALL 2008-04-30 14:49:15.862200000 -0400 | |
42 | +++ nfs-utils-1.1.2-kwc/utils/gssd/gssd.h 2008-04-30 14:49:17.073538000 -0400 | |
43 | @@ -50,6 +50,7 @@ | |
44 | #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" | |
45 | #define GSSD_SERVICE_NAME "nfs" | |
46 | #define GSSD_SERVICE_NAME_LEN 3 | |
47 | +#define GSSD_MAX_CCACHE_SEARCH 16 | |
0ac65518 | 48 | |
12480a97 JB |
49 | /* |
50 | * The gss mechanisms that we can handle | |
51 | @@ -61,7 +62,7 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT | |
52 | extern char pipefs_dir[PATH_MAX]; | |
53 | extern char pipefs_nfsdir[PATH_MAX]; | |
54 | extern char keytabfile[PATH_MAX]; | |
55 | -extern char ccachedir[PATH_MAX]; | |
56 | +extern char *ccachesearch[]; | |
57 | extern int use_memcache; | |
58 | extern int root_uses_machine_creds; | |
97cc26d8 | 59 | |
12480a97 JB |
60 | @@ -80,6 +81,7 @@ struct clnt_info { |
61 | int krb5_poll_index; | |
62 | int spkm3_fd; | |
63 | int spkm3_poll_index; | |
64 | + int port; | |
0ac65518 JB |
65 | }; |
66 | ||
12480a97 | 67 | void init_client_list(void); |
0ac65518 | 68 | diff -puN utils/gssd/gssd_proc.c~CITI_NFS4_ALL utils/gssd/gssd_proc.c |
12480a97 JB |
69 | --- nfs-utils-1.1.2/utils/gssd/gssd_proc.c~CITI_NFS4_ALL 2008-04-30 14:49:15.986076000 -0400 |
70 | +++ nfs-utils-1.1.2-kwc/utils/gssd/gssd_proc.c 2008-04-30 14:49:17.167444000 -0400 | |
0ac65518 JB |
71 | @@ -102,7 +102,7 @@ int pollsize; /* the size of pollaray ( |
72 | /* XXX buffer problems: */ | |
73 | static int | |
74 | read_service_info(char *info_file_name, char **servicename, char **servername, | |
75 | - int *prog, int *vers, char **protocol) { | |
76 | + int *prog, int *vers, char **protocol, int *port) { | |
77 | #define INFOBUFLEN 256 | |
78 | char buf[INFOBUFLEN]; | |
79 | static char dummy[128]; | |
12480a97 | 80 | @@ -112,6 +112,8 @@ read_service_info(char *info_file_name, |
0ac65518 JB |
81 | char program[16]; |
82 | char version[16]; | |
83 | char protoname[16]; | |
0ac65518 JB |
84 | + char cb_port[128]; |
85 | + char *p; | |
86 | in_addr_t inaddr; | |
87 | int fd = -1; | |
88 | struct hostent *ent = NULL; | |
12480a97 | 89 | @@ -143,6 +145,10 @@ read_service_info(char *info_file_name, |
0ac65518 JB |
90 | goto fail; |
91 | } | |
92 | ||
0ac65518 JB |
93 | + cb_port[0] = '\0'; |
94 | + if ((p = strstr(buf, "port")) != NULL) | |
95 | + sscanf(p, "port: %127s\n", cb_port); | |
14bcaf3a | 96 | + |
0ac65518 | 97 | /* check service, program, and version */ |
12480a97 | 98 | if(memcmp(service, "nfs", 3)) return -1; |
0ac65518 | 99 | *prog = atoi(program + 1); /* skip open paren */ |
12480a97 | 100 | @@ -163,6 +169,8 @@ read_service_info(char *info_file_name, |
0ac65518 JB |
101 | if (!(*servicename = calloc(strlen(buf) + 1, 1))) |
102 | goto fail; | |
103 | memcpy(*servicename, buf, strlen(buf)); | |
12480a97 JB |
104 | + if (cb_port[0] != '\0') |
105 | + *port = atoi(cb_port); | |
0ac65518 | 106 | |
12480a97 JB |
107 | if (!(*protocol = strdup(protoname))) |
108 | goto fail; | |
109 | @@ -238,7 +246,7 @@ process_clnt_dir_files(struct clnt_info | |
0ac65518 JB |
110 | if ((clp->servicename == NULL) && |
111 | read_service_info(info_file_name, &clp->servicename, | |
112 | &clp->servername, &clp->prog, &clp->vers, | |
113 | - &clp->protocol)) | |
114 | + &clp->protocol, &clp->port)) | |
115 | return -1; | |
116 | return 0; | |
117 | } | |
12480a97 | 118 | @@ -587,6 +595,8 @@ int create_auth_rpc_client(struct clnt_i |
0ac65518 JB |
119 | clp->servername, uid); |
120 | goto out_fail; | |
97cc26d8 | 121 | } |
0ac65518 JB |
122 | + if (clp->port) |
123 | + ((struct sockaddr_in *)a->ai_addr)->sin_port = htons(clp->port); | |
124 | if (a->ai_protocol == IPPROTO_TCP) { | |
125 | if ((rpc_clnt = clnttcp_create( | |
126 | (struct sockaddr_in *) a->ai_addr, | |
12480a97 JB |
127 | @@ -675,6 +685,7 @@ handle_krb5_upcall(struct clnt_info *clp |
128 | gss_buffer_desc token; | |
129 | char **credlist = NULL; | |
0ac65518 | 130 | char **ccname; |
12480a97 | 131 | + char **dirname; |
0ac65518 | 132 | int create_resp = -1; |
97cc26d8 | 133 | |
12480a97 JB |
134 | printerr(1, "handling krb5 upcall\n"); |
135 | @@ -691,10 +702,14 @@ handle_krb5_upcall(struct clnt_info *clp | |
136 | ||
137 | if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) { | |
138 | /* Tell krb5 gss which credentials cache to use */ | |
139 | - gssd_setup_krb5_user_gss_ccache(uid, clp->servername); | |
140 | + for (dirname = ccachesearch; *dirname != NULL; dirname++) { | |
141 | + gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname); | |
142 | ||
143 | - create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, | |
144 | - AUTHTYPE_KRB5); | |
145 | + create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, | |
146 | + AUTHTYPE_KRB5); | |
147 | + if (create_resp == 0) | |
148 | + break; | |
149 | + } | |
150 | } | |
151 | if (create_resp != 0) { | |
152 | if (uid == 0 && root_uses_machine_creds == 1) { | |
0ac65518 | 153 | diff -puN utils/gssd/krb5_util.c~CITI_NFS4_ALL utils/gssd/krb5_util.c |
12480a97 JB |
154 | --- nfs-utils-1.1.2/utils/gssd/krb5_util.c~CITI_NFS4_ALL 2008-04-30 14:49:16.274848000 -0400 |
155 | +++ nfs-utils-1.1.2-kwc/utils/gssd/krb5_util.c 2008-04-30 14:49:17.571397000 -0400 | |
0ac65518 JB |
156 | @@ -97,6 +97,7 @@ |
157 | #include "config.h" | |
158 | #include <sys/param.h> | |
159 | #include <rpc/rpc.h> | |
160 | +#include <sys/types.h> | |
161 | #include <sys/stat.h> | |
162 | #include <sys/socket.h> | |
163 | #include <arpa/inet.h> | |
164 | @@ -108,6 +109,7 @@ | |
165 | #include <dirent.h> | |
166 | #include <netdb.h> | |
167 | #include <ctype.h> | |
168 | +#include <fcntl.h> | |
169 | #include <errno.h> | |
170 | #include <time.h> | |
171 | #include <gssapi/gssapi.h> | |
12480a97 | 172 | @@ -126,12 +128,17 @@ |
0ac65518 JB |
173 | /* Global list of principals/cache file names for machine credentials */ |
174 | struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL; | |
175 | ||
176 | +/* Encryption types supported by the kernel rpcsec_gss code */ | |
177 | +int num_krb5_enctypes = 0; | |
178 | +krb5_enctype *krb5_enctypes = NULL; | |
179 | + | |
180 | /*==========================*/ | |
181 | /*=== Internal routines ===*/ | |
182 | /*==========================*/ | |
12480a97 JB |
183 | |
184 | static int select_krb5_ccache(const struct dirent *d); | |
185 | -static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d); | |
186 | +static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, | |
187 | + struct dirent **d); | |
188 | static int gssd_get_single_krb5_cred(krb5_context context, | |
189 | krb5_keytab kt, struct gssd_k5_kt_princ *ple); | |
190 | ||
191 | @@ -159,7 +166,7 @@ select_krb5_ccache(const struct dirent * | |
192 | } | |
193 | ||
194 | /* | |
195 | - * Look in the ccachedir for files that look like they | |
196 | + * Look in directory "dirname" for files that look like they | |
197 | * are Kerberos Credential Cache files for a given UID. Return | |
198 | * non-zero and the dirent pointer for the entry most likely to be | |
199 | * what we want. Otherwise, return zero and no dirent pointer. | |
200 | @@ -170,7 +177,7 @@ select_krb5_ccache(const struct dirent * | |
201 | * 1 => found an existing entry | |
202 | */ | |
203 | static int | |
204 | -gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d) | |
205 | +gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) | |
206 | { | |
207 | struct dirent **namelist; | |
208 | int n; | |
209 | @@ -181,9 +188,10 @@ gssd_find_existing_krb5_ccache(uid_t uid | |
210 | ||
211 | memset(&best_match_stat, 0, sizeof(best_match_stat)); | |
212 | *d = NULL; | |
213 | - n = scandir(ccachedir, &namelist, select_krb5_ccache, 0); | |
214 | + n = scandir(dirname, &namelist, select_krb5_ccache, 0); | |
215 | if (n < 0) { | |
216 | - perror("scandir looking for krb5 credentials caches"); | |
217 | + printerr(1, "Error doing scandir on directory '%s': %s\n", | |
218 | + dirname, strerror(errno)); | |
219 | } | |
220 | else if (n > 0) { | |
221 | char statname[1024]; | |
222 | @@ -191,7 +199,7 @@ gssd_find_existing_krb5_ccache(uid_t uid | |
223 | printerr(3, "CC file '%s' being considered\n", | |
224 | namelist[i]->d_name); | |
225 | snprintf(statname, sizeof(statname), | |
226 | - "%s/%s", ccachedir, namelist[i]->d_name); | |
227 | + "%s/%s", dirname, namelist[i]->d_name); | |
228 | if (lstat(statname, &tmp_stat)) { | |
229 | printerr(0, "Error doing stat on file '%s'\n", | |
230 | statname); | |
231 | @@ -256,58 +264,6 @@ gssd_find_existing_krb5_ccache(uid_t uid | |
0ac65518 | 232 | return found; |
97cc26d8 JB |
233 | } |
234 | ||
0ac65518 JB |
235 | - |
236 | -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
237 | -/* | |
238 | - * this routine obtains a credentials handle via gss_acquire_cred() | |
239 | - * then calls gss_krb5_set_allowable_enctypes() to limit the encryption | |
240 | - * types negotiated. | |
241 | - * | |
242 | - * XXX Should call some function to determine the enctypes supported | |
243 | - * by the kernel. (Only need to do that once!) | |
244 | - * | |
245 | - * Returns: | |
246 | - * 0 => all went well | |
247 | - * -1 => there was an error | |
248 | - */ | |
249 | - | |
250 | -int | |
251 | -limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) | |
252 | -{ | |
253 | - u_int maj_stat, min_stat; | |
254 | - gss_cred_id_t credh; | |
255 | - gss_OID_set_desc desired_mechs; | |
256 | - krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC }; | |
257 | - int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); | |
258 | - | |
259 | - /* We only care about getting a krb5 cred */ | |
260 | - desired_mechs.count = 1; | |
261 | - desired_mechs.elements = &krb5oid; | |
262 | - | |
263 | - maj_stat = gss_acquire_cred(&min_stat, NULL, 0, | |
264 | - &desired_mechs, GSS_C_INITIATE, | |
265 | - &credh, NULL, NULL); | |
266 | - | |
267 | - if (maj_stat != GSS_S_COMPLETE) { | |
268 | - pgsserr("gss_acquire_cred", | |
269 | - maj_stat, min_stat, &krb5oid); | |
270 | - return -1; | |
271 | - } | |
272 | - | |
273 | - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid, | |
274 | - num_enctypes, &enctypes); | |
275 | - if (maj_stat != GSS_S_COMPLETE) { | |
276 | - pgsserr("gss_set_allowable_enctypes", | |
277 | - maj_stat, min_stat, &krb5oid); | |
278 | - gss_release_cred(&min_stat, &credh); | |
279 | - return -1; | |
280 | - } | |
281 | - sec->cred = credh; | |
282 | - | |
283 | - return 0; | |
284 | -} | |
285 | -#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ | |
286 | - | |
14bcaf3a | 287 | /* |
0ac65518 JB |
288 | * Obtain credentials via a key in the keytab given |
289 | * a keytab handle and a gssd_k5_kt_princ structure. | |
12480a97 JB |
290 | @@ -404,7 +360,7 @@ gssd_get_single_krb5_cred(krb5_context c |
291 | cache_type = "FILE"; | |
292 | snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", | |
293 | cache_type, | |
294 | - ccachedir, GSSD_DEFAULT_CRED_PREFIX, | |
295 | + ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX, | |
296 | GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); | |
297 | ple->endtime = my_creds.times.endtime; | |
298 | if (ple->ccname != NULL) | |
299 | @@ -879,6 +835,56 @@ out: | |
0ac65518 JB |
300 | return retval; |
301 | } | |
302 | ||
303 | +/* | |
304 | + * Parse the supported encryption type information | |
14bcaf3a | 305 | + */ |
0ac65518 JB |
306 | +static int |
307 | +parse_enctypes(char *enctypes) | |
97cc26d8 | 308 | +{ |
0ac65518 JB |
309 | + int n = 0; |
310 | + char *curr, *comma; | |
311 | + int i; | |
14bcaf3a | 312 | + |
0ac65518 JB |
313 | + /* Just in case this ever gets called more than once */ |
314 | + if (krb5_enctypes != NULL) { | |
315 | + free(krb5_enctypes); | |
316 | + krb5_enctypes = NULL; | |
317 | + num_krb5_enctypes = 0; | |
97cc26d8 | 318 | + } |
0ac65518 JB |
319 | + |
320 | + /* count the number of commas */ | |
321 | + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) { | |
322 | + comma = strchr(curr, ','); | |
323 | + if (comma != NULL) | |
324 | + n++; | |
325 | + else | |
326 | + break; | |
14bcaf3a | 327 | + } |
0ac65518 JB |
328 | + /* If no more commas and we're not at the end, there's one more value */ |
329 | + if (*curr != '\0') | |
330 | + n++; | |
97cc26d8 | 331 | + |
0ac65518 JB |
332 | + /* Empty string, return an error */ |
333 | + if (n == 0) | |
334 | + return ENOENT; | |
335 | + | |
336 | + /* Allocate space for enctypes array */ | |
337 | + if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) { | |
338 | + return ENOMEM; | |
339 | + } | |
340 | + | |
341 | + /* Now parse each value into the array */ | |
342 | + for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) { | |
343 | + krb5_enctypes[i++] = atoi(curr); | |
344 | + comma = strchr(curr, ','); | |
345 | + if (comma == NULL) | |
346 | + break; | |
347 | + } | |
348 | + | |
349 | + num_krb5_enctypes = n; | |
350 | + return 0; | |
97cc26d8 JB |
351 | +} |
352 | + | |
0ac65518 JB |
353 | /*==========================*/ |
354 | /*=== External routines ===*/ | |
355 | /*==========================*/ | |
12480a97 JB |
356 | @@ -892,7 +898,7 @@ out: |
357 | * void | |
358 | */ | |
359 | void | |
360 | -gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername) | |
361 | +gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirname) | |
362 | { | |
363 | char buf[MAX_NETOBJ_SZ]; | |
364 | struct dirent *d; | |
365 | @@ -900,14 +906,13 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui | |
366 | printerr(2, "getting credentials for client with uid %u for " | |
367 | "server %s\n", uid, servername); | |
368 | memset(buf, 0, sizeof(buf)); | |
369 | - if (gssd_find_existing_krb5_ccache(uid, &d)) { | |
370 | - snprintf(buf, sizeof(buf), "FILE:%s/%s", | |
371 | - ccachedir, d->d_name); | |
372 | + if (gssd_find_existing_krb5_ccache(uid, dirname, &d)) { | |
373 | + snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, d->d_name); | |
374 | free(d); | |
375 | } | |
376 | else | |
377 | snprintf(buf, sizeof(buf), "FILE:%s/%s%u", | |
378 | - ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid); | |
379 | + dirname, GSSD_DEFAULT_CRED_PREFIX, uid); | |
380 | printerr(2, "using %s as credentials cache for client with " | |
381 | "uid %u for server %s\n", buf, uid, servername); | |
382 | gssd_set_krb5_ccache_name(buf); | |
383 | @@ -1129,3 +1134,133 @@ gssd_k5_err_msg(krb5_context context, kr | |
0ac65518 JB |
384 | return error_message(code); |
385 | #endif | |
386 | } | |
387 | + | |
388 | +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
389 | +/* | |
390 | + * this routine obtains a credentials handle via gss_acquire_cred() | |
391 | + * then calls gss_krb5_set_allowable_enctypes() to limit the encryption | |
392 | + * types negotiated. | |
393 | + * | |
12480a97 JB |
394 | + * XXX Should call some function to determine the enctypes supported |
395 | + * by the kernel. (Only need to do that once!) | |
396 | + * | |
0ac65518 JB |
397 | + * Returns: |
398 | + * 0 => all went well | |
399 | + * -1 => there was an error | |
97cc26d8 | 400 | + */ |
0ac65518 JB |
401 | + |
402 | +int | |
403 | +limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) | |
97cc26d8 | 404 | +{ |
0ac65518 JB |
405 | + u_int maj_stat, min_stat; |
406 | + gss_cred_id_t credh; | |
407 | + gss_OID_set_desc desired_mechs; | |
12480a97 JB |
408 | + krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC, |
409 | + ENCTYPE_DES_CBC_MD5, | |
410 | + ENCTYPE_DES_CBC_MD4 }; | |
0ac65518 JB |
411 | + int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); |
412 | + | |
413 | + /* We only care about getting a krb5 cred */ | |
414 | + desired_mechs.count = 1; | |
415 | + desired_mechs.elements = &krb5oid; | |
416 | + | |
417 | + maj_stat = gss_acquire_cred(&min_stat, NULL, 0, | |
418 | + &desired_mechs, GSS_C_INITIATE, | |
419 | + &credh, NULL, NULL); | |
420 | + | |
421 | + if (maj_stat != GSS_S_COMPLETE) { | |
12480a97 JB |
422 | + if (get_verbosity() > 0) |
423 | + pgsserr("gss_acquire_cred", | |
424 | + maj_stat, min_stat, &krb5oid); | |
0ac65518 | 425 | + return -1; |
97cc26d8 | 426 | + } |
0ac65518 JB |
427 | + |
428 | + /* | |
429 | + * If we failed for any reason to produce global | |
430 | + * list of supported enctypes, use local default here. | |
431 | + */ | |
432 | + if (krb5_enctypes == NULL) | |
433 | + maj_stat = gss_set_allowable_enctypes(&min_stat, credh, | |
434 | + &krb5oid, num_enctypes, &enctypes); | |
435 | + else | |
436 | + maj_stat = gss_set_allowable_enctypes(&min_stat, credh, | |
437 | + &krb5oid, num_krb5_enctypes, | |
438 | + krb5_enctypes); | |
439 | + if (maj_stat != GSS_S_COMPLETE) { | |
440 | + pgsserr("gss_set_allowable_enctypes", | |
441 | + maj_stat, min_stat, &krb5oid); | |
12480a97 | 442 | + gss_release_cred(&min_stat, &credh); |
0ac65518 JB |
443 | + return -1; |
444 | + } | |
445 | + sec->cred = credh; | |
446 | + | |
447 | + return 0; | |
97cc26d8 | 448 | +} |
0ac65518 | 449 | +#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ |
97cc26d8 | 450 | + |
0ac65518 JB |
451 | +/* |
452 | + * Obtain supported enctypes from kernel. | |
453 | + * Set defaults if info is not available. | |
454 | + */ | |
455 | +void | |
456 | +gssd_obtain_kernel_krb5_info(void) | |
97cc26d8 | 457 | +{ |
0ac65518 JB |
458 | + char enctype_file_name[128]; |
459 | + char buf[1024]; | |
460 | + char enctypes[128]; | |
461 | + int nscanned; | |
462 | + int fd; | |
463 | + int use_default_enctypes = 0; | |
464 | + int nbytes, numfields; | |
465 | + char default_enctypes[] = "1,3,2"; | |
466 | + int code; | |
14bcaf3a | 467 | + |
0ac65518 JB |
468 | + snprintf(enctype_file_name, sizeof(enctype_file_name), |
469 | + "%s/%s", pipefs_dir, "krb5_info"); | |
470 | + | |
471 | + if ((fd = open(enctype_file_name, O_RDONLY)) == -1) { | |
472 | + printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: " | |
473 | + "Unable to open '%s'. Unable to determine " | |
474 | + "Kerberos encryption types supported by the " | |
475 | + "kernel; using defaults (%s).\n", | |
476 | + enctype_file_name, default_enctypes); | |
477 | + use_default_enctypes = 1; | |
478 | + goto do_the_parse; | |
479 | + } | |
480 | + memset(buf, 0, sizeof(buf)); | |
481 | + if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) { | |
482 | + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " | |
483 | + "Error reading Kerberos encryption type " | |
484 | + "information file '%s'; using defaults (%s).\n", | |
485 | + enctype_file_name, default_enctypes); | |
486 | + use_default_enctypes = 1; | |
487 | + close(fd); | |
488 | + goto do_the_parse; | |
489 | + } | |
490 | + close(fd); | |
491 | + numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned); | |
492 | + if (numfields < 1) { | |
493 | + printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " | |
494 | + "error parsing Kerberos encryption type " | |
495 | + "information from file '%s'; using defaults (%s).\n", | |
496 | + enctype_file_name, default_enctypes); | |
497 | + use_default_enctypes = 1; | |
498 | + goto do_the_parse; | |
499 | + } | |
500 | + if (nbytes > nscanned) { | |
501 | + printerr(2, "gssd_obtain_kernel_krb5_info: " | |
502 | + "Ignoring extra information, '%s', from '%s'\n", | |
503 | + buf+nscanned, enctype_file_name); | |
504 | + goto do_the_parse; | |
505 | + } | |
506 | + do_the_parse: | |
12480a97 | 507 | + if (use_default_enctypes) |
0ac65518 | 508 | + strcpy(enctypes, default_enctypes); |
14bcaf3a | 509 | + |
0ac65518 JB |
510 | + if ((code = parse_enctypes(enctypes)) != 0) { |
511 | + printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: " | |
512 | + "parse_enctypes%s failed with code %d\n", | |
513 | + use_default_enctypes ? " (with default enctypes)" : "", | |
514 | + code); | |
97cc26d8 JB |
515 | + } |
516 | +} | |
12480a97 JB |
517 | diff -puN utils/gssd/err_util.c~CITI_NFS4_ALL utils/gssd/err_util.c |
518 | --- nfs-utils-1.1.2/utils/gssd/err_util.c~CITI_NFS4_ALL 2008-04-30 14:49:16.478848000 -0400 | |
519 | +++ nfs-utils-1.1.2-kwc/utils/gssd/err_util.c 2008-04-30 14:49:16.616849000 -0400 | |
520 | @@ -60,3 +60,8 @@ void printerr(int priority, char *format | |
521 | xlog_backend(L_ERROR, format, args); | |
522 | va_end(args); | |
523 | } | |
524 | + | |
525 | +int get_verbosity(void) | |
526 | +{ | |
527 | + return verbosity; | |
528 | +} | |
529 | diff -puN utils/gssd/err_util.h~CITI_NFS4_ALL utils/gssd/err_util.h | |
530 | --- nfs-utils-1.1.2/utils/gssd/err_util.h~CITI_NFS4_ALL 2008-04-30 14:49:16.574848000 -0400 | |
531 | +++ nfs-utils-1.1.2-kwc/utils/gssd/err_util.h 2008-04-30 14:49:16.633848000 -0400 | |
532 | @@ -33,5 +33,6 @@ | |
533 | ||
534 | void initerr(char *progname, int verbosity, int fg); | |
535 | void printerr(int priority, char *format, ...); | |
536 | +int get_verbosity(void); | |
537 | ||
538 | #endif /* _ERR_UTIL_H_ */ | |
539 | diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c | |
540 | --- nfs-utils-1.1.2/utils/gssd/gssd.c~CITI_NFS4_ALL 2008-04-30 14:49:16.799812000 -0400 | |
541 | +++ nfs-utils-1.1.2-kwc/utils/gssd/gssd.c 2008-04-30 14:49:17.507397000 -0400 | |
542 | @@ -57,6 +57,7 @@ char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_ | |
543 | char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR; | |
544 | char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE; | |
545 | char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR; | |
546 | +char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1]; | |
547 | int use_memcache = 0; | |
548 | int root_uses_machine_creds = 1; | |
549 | ||
550 | @@ -93,9 +94,11 @@ main(int argc, char *argv[]) | |
551 | int verbosity = 0; | |
552 | int rpc_verbosity = 0; | |
553 | int opt; | |
554 | + int i; | |
555 | extern char *optarg; | |
556 | char *progname; | |
557 | ||
558 | + memset(ccachesearch, 0, sizeof(ccachesearch)); | |
559 | while ((opt = getopt(argc, argv, "fvrmnMp:k:d:")) != -1) { | |
560 | switch (opt) { | |
561 | case 'f': | |
562 | @@ -136,6 +139,13 @@ main(int argc, char *argv[]) | |
563 | break; | |
564 | } | |
565 | } | |
566 | + | |
567 | + i = 0; | |
568 | + ccachesearch[i++] = strtok(ccachedir, ":"); | |
569 | + do { | |
570 | + ccachesearch[i++] = strtok(NULL, ":"); | |
571 | + } while (ccachesearch[i-1] != NULL && i < GSSD_MAX_CCACHE_SEARCH); | |
572 | + | |
573 | snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s", | |
574 | pipefs_dir, GSSD_SERVICE_NAME); | |
575 | if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0') | |
576 | @@ -165,6 +175,9 @@ main(int argc, char *argv[]) | |
577 | signal(SIGTERM, sig_die); | |
578 | signal(SIGHUP, sig_hup); | |
579 | ||
580 | + /* Determine Kerberos information from the kernel */ | |
581 | + gssd_obtain_kernel_krb5_info(); | |
582 | + | |
583 | gssd_run(); | |
584 | printerr(0, "gssd_run returned!\n"); | |
585 | abort(); | |
586 | diff -puN utils/gssd/gssd.man~CITI_NFS4_ALL utils/gssd/gssd.man | |
587 | --- nfs-utils-1.1.2/utils/gssd/gssd.man~CITI_NFS4_ALL 2008-04-30 14:49:16.899712000 -0400 | |
588 | +++ nfs-utils-1.1.2-kwc/utils/gssd/gssd.man 2008-04-30 14:49:17.121490000 -0400 | |
589 | @@ -74,7 +74,11 @@ where to look for the rpc_pipefs filesys | |
590 | .B -d directory | |
591 | Tells | |
592 | .B rpc.gssd | |
593 | -where to look for kerberos credential files. The default value is "/tmp". | |
594 | +where to look for Kerberos credential files. The default value is "/tmp". | |
595 | +This can also be a colon separated list of directories to be searched | |
596 | +for Kerberos credential files. Note that if machine credentials are being | |
597 | +stored in files, then the first directory on this list is where the | |
598 | +machine credentials are stored. | |
599 | .TP | |
600 | .B -v | |
601 | Increases the verbosity of the output (can be specified multiple times). | |
0ac65518 | 602 | diff -puN utils/gssd/krb5_util.h~CITI_NFS4_ALL utils/gssd/krb5_util.h |
12480a97 JB |
603 | --- nfs-utils-1.1.2/utils/gssd/krb5_util.h~CITI_NFS4_ALL 2008-04-30 14:49:17.008603000 -0400 |
604 | +++ nfs-utils-1.1.2-kwc/utils/gssd/krb5_util.h 2008-04-30 14:49:17.589397000 -0400 | |
605 | @@ -17,7 +17,8 @@ struct gssd_k5_kt_princ { | |
606 | }; | |
607 | ||
608 | ||
609 | -void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername); | |
610 | +void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, | |
611 | + char *dirname); | |
612 | int gssd_get_krb5_machine_cred_list(char ***list); | |
613 | void gssd_free_krb5_machine_cred_list(char **list); | |
614 | void gssd_setup_krb5_machine_gss_ccache(char *servername); | |
615 | @@ -26,6 +27,8 @@ int gssd_refresh_krb5_machine_credentia | |
0ac65518 JB |
616 | struct gssd_k5_kt_princ *ple); |
617 | const char * | |
618 | gssd_k5_err_msg(krb5_context context, krb5_error_code code); | |
619 | +void gssd_obtain_kernel_krb5_info(void); | |
620 | + | |
621 | ||
622 | #ifdef HAVE_SET_ALLOWABLE_ENCTYPES | |
623 | int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); | |
624 | diff -puN utils/gssd/context.h~CITI_NFS4_ALL utils/gssd/context.h | |
12480a97 JB |
625 | --- nfs-utils-1.1.2/utils/gssd/context.h~CITI_NFS4_ALL 2008-04-30 14:49:17.768393000 -0400 |
626 | +++ nfs-utils-1.1.2-kwc/utils/gssd/context.h 2008-04-30 14:49:18.056105000 -0400 | |
0ac65518 JB |
627 | @@ -1,5 +1,5 @@ |
628 | /* | |
629 | - Copyright (c) 2004 The Regents of the University of Michigan. | |
12480a97 | 630 | + Copyright (c) 2004,2008 The Regents of the University of Michigan. |
0ac65518 JB |
631 | All rights reserved. |
632 | ||
633 | Redistribution and use in source and binary forms, with or without | |
634 | @@ -36,6 +36,10 @@ | |
635 | /* Hopefully big enough to hold any serialized context */ | |
636 | #define MAX_CTX_LEN 4096 | |
637 | ||
638 | +/* New context format flag values */ | |
639 | +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
640 | +#define KRB5_CTX_FLAG_CFX 0x00000002 | |
641 | +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
642 | ||
643 | int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf, | |
644 | gss_OID mech); | |
645 | diff -puN utils/gssd/context_lucid.c~CITI_NFS4_ALL utils/gssd/context_lucid.c | |
12480a97 JB |
646 | --- nfs-utils-1.1.2/utils/gssd/context_lucid.c~CITI_NFS4_ALL 2008-04-30 14:49:17.907254000 -0400 |
647 | +++ nfs-utils-1.1.2-kwc/utils/gssd/context_lucid.c 2008-04-30 14:49:18.075086000 -0400 | |
0ac65518 JB |
648 | @@ -40,6 +40,7 @@ |
649 | #include <stdio.h> | |
650 | #include <syslog.h> | |
651 | #include <string.h> | |
652 | +#include <errno.h> | |
653 | #include "gss_util.h" | |
654 | #include "gss_oids.h" | |
655 | #include "err_util.h" | |
656 | @@ -113,15 +114,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_luc | |
657 | * Note that the rfc1964 version only supports DES enctypes. | |
658 | */ | |
659 | if (lctx->rfc1964_kd.ctx_key.type != 4) { | |
660 | - printerr(1, "prepare_krb5_rfc1964_buffer: " | |
661 | - "overriding heimdal keytype (%d => %d)\n", | |
662 | - lctx->rfc1964_kd.ctx_key.type, 4); | |
663 | + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n", | |
664 | + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4); | |
665 | lctx->rfc1964_kd.ctx_key.type = 4; | |
666 | } | |
667 | #endif | |
668 | - printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " | |
669 | - "enctype %d and length %d\n", | |
670 | - lctx->rfc1964_kd.ctx_key.type, | |
671 | + printerr(2, "%s: serializing keys with enctype %d and length %d\n", | |
672 | + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, | |
673 | lctx->rfc1964_kd.ctx_key.length); | |
674 | ||
675 | /* derive the encryption key and copy it into buffer */ | |
12480a97 | 676 | @@ -152,15 +151,102 @@ out_err: |
0ac65518 JB |
677 | return -1; |
678 | } | |
679 | ||
0ac65518 JB |
680 | +/* Flags for version 2 context flags */ |
681 | +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
682 | +#define KRB5_CTX_FLAG_CFX 0x00000002 | |
683 | +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
684 | + | |
14bcaf3a | 685 | +/* |
0ac65518 JB |
686 | + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx), |
687 | + * to send to the kernel for newer encryption types -- or for DES3. | |
688 | + * | |
689 | + * The new format is: | |
690 | + * | |
0ac65518 JB |
691 | + * u32 flags; |
692 | + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 | |
693 | + * #define KRB5_CTX_FLAG_CFX 0x00000002 | |
694 | + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
12480a97 | 695 | + * s32 endtime; |
0ac65518 | 696 | + * u64 seq_send; |
12480a97 JB |
697 | + * u32 enctype; ( encrption type of key ) |
698 | + * raw key; ( raw key bytes (kernel will derive)) | |
0ac65518 JB |
699 | + * |
700 | + */ | |
12480a97 JB |
701 | static int |
702 | -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx, | |
703 | - gss_buffer_desc *buf) | |
0ac65518 JB |
704 | +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx, |
705 | + gss_buffer_desc *buf) | |
12480a97 JB |
706 | { |
707 | - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n"); | |
708 | - return -1; | |
709 | -} | |
0ac65518 JB |
710 | + char *p, *end; |
711 | + uint32_t v2_flags = 0; | |
0ac65518 JB |
712 | + uint32_t enctype; |
713 | + uint32_t keysize; | |
12480a97 | 714 | |
0ac65518 JB |
715 | + if (!(buf->value = calloc(1, MAX_CTX_LEN))) |
716 | + goto out_err; | |
717 | + p = buf->value; | |
718 | + end = buf->value + MAX_CTX_LEN; | |
12480a97 | 719 | |
0ac65518 | 720 | + /* Version 2 */ |
0ac65518 JB |
721 | + if (lctx->initiate) |
722 | + v2_flags |= KRB5_CTX_FLAG_INITIATOR; | |
723 | + if (lctx->protocol != 0) | |
724 | + v2_flags |= KRB5_CTX_FLAG_CFX; | |
725 | + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) | |
726 | + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; | |
727 | + | |
728 | + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; | |
12480a97 | 729 | + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; |
0ac65518 JB |
730 | + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; |
731 | + | |
732 | + /* Protocol 0 here implies DES3 or RC4 */ | |
733 | + printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol); | |
734 | + if (lctx->protocol == 0) { | |
735 | + enctype = lctx->rfc1964_kd.ctx_key.type; | |
0ac65518 | 736 | + keysize = lctx->rfc1964_kd.ctx_key.length; |
0ac65518 JB |
737 | + } else { |
738 | + if (lctx->cfx_kd.have_acceptor_subkey) { | |
739 | + enctype = lctx->cfx_kd.acceptor_subkey.type; | |
740 | + keysize = lctx->cfx_kd.acceptor_subkey.length; | |
741 | + } else { | |
742 | + enctype = lctx->cfx_kd.ctx_key.type; | |
743 | + keysize = lctx->cfx_kd.ctx_key.length; | |
744 | + } | |
0ac65518 | 745 | + } |
12480a97 JB |
746 | + printerr(2, "%s: serializing key with enctype %d and size %d\n", |
747 | + __FUNCTION__, enctype, keysize); | |
748 | + | |
0ac65518 | 749 | + if (WRITE_BYTES(&p, end, enctype)) goto out_err; |
0ac65518 JB |
750 | + |
751 | + if (lctx->protocol == 0) { | |
0ac65518 JB |
752 | + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, |
753 | + lctx->rfc1964_kd.ctx_key.length)) | |
754 | + goto out_err; | |
0ac65518 | 755 | + } else { |
12480a97 JB |
756 | + if (lctx->cfx_kd.have_acceptor_subkey) { |
757 | + if (write_bytes(&p, end, | |
758 | + lctx->cfx_kd.acceptor_subkey.data, | |
759 | + lctx->cfx_kd.acceptor_subkey.length)) | |
760 | + goto out_err; | |
0ac65518 | 761 | + } else { |
12480a97 JB |
762 | + if (write_bytes(&p, end, lctx->cfx_kd.ctx_key.data, |
763 | + lctx->cfx_kd.ctx_key.length)) | |
764 | + goto out_err; | |
0ac65518 | 765 | + } |
0ac65518 JB |
766 | + } |
767 | + | |
768 | + buf->length = p - (char *)buf->value; | |
769 | + return 0; | |
770 | + | |
771 | +out_err: | |
772 | + printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n", | |
773 | + __FUNCTION__); | |
774 | + if (buf->value) { | |
775 | + free(buf->value); | |
776 | + buf->value = NULL; | |
777 | + } | |
778 | + buf->length = 0; | |
0ac65518 JB |
779 | + return -1; |
780 | +} | |
781 | int | |
782 | serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) | |
97cc26d8 | 783 | { |
12480a97 | 784 | @@ -170,7 +256,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss |
0ac65518 JB |
785 | gss_krb5_lucid_context_v1_t *lctx = 0; |
786 | int retcode = 0; | |
97cc26d8 | 787 | |
0ac65518 JB |
788 | - printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n"); |
789 | + printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__); | |
790 | maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx, | |
791 | 1, &return_ctx); | |
792 | if (maj_stat != GSS_S_COMPLETE) { | |
12480a97 | 793 | @@ -192,11 +278,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss |
0ac65518 JB |
794 | break; |
795 | } | |
97cc26d8 | 796 | |
0ac65518 JB |
797 | - /* Now lctx points to a lucid context that we can send down to kernel */ |
798 | - if (lctx->protocol == 0) | |
799 | + /* | |
800 | + * Now lctx points to a lucid context that we can send down to kernel | |
801 | + * | |
802 | + * Note: we send down different information to the kernel depending | |
803 | + * on the protocol version and the enctyption type. | |
804 | + * For protocol version 0 with all enctypes besides DES3, we use | |
805 | + * the original format. For protocol version != 0 or DES3, we | |
806 | + * send down the new style information. | |
807 | + */ | |
808 | + | |
809 | + if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4) | |
810 | retcode = prepare_krb5_rfc1964_buffer(lctx, buf); | |
811 | else | |
812 | - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf); | |
813 | + retcode = prepare_krb5_rfc4121_buffer(lctx, buf); | |
97cc26d8 | 814 | |
0ac65518 JB |
815 | maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); |
816 | if (maj_stat != GSS_S_COMPLETE) { | |
12480a97 | 817 | @@ -206,8 +301,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss |
0ac65518 | 818 | } |
97cc26d8 | 819 | |
0ac65518 JB |
820 | if (retcode) { |
821 | - printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer " | |
822 | - "failed (retcode = %d)\n", retcode); | |
823 | + printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n", | |
824 | + __FUNCTION__, retcode); | |
825 | goto out_err; | |
826 | } | |
97cc26d8 | 827 | |
12480a97 | 828 | @@ -217,4 +312,7 @@ out_err: |
0ac65518 JB |
829 | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); |
830 | return -1; | |
831 | } | |
97cc26d8 | 832 | + |
97cc26d8 | 833 | + |
0ac65518 JB |
834 | + |
835 | #endif /* HAVE_LUCID_CONTEXT_SUPPORT */ | |
836 | diff -puN utils/gssd/context_mit.c~CITI_NFS4_ALL utils/gssd/context_mit.c | |
12480a97 JB |
837 | --- nfs-utils-1.1.2/utils/gssd/context_mit.c~CITI_NFS4_ALL 2008-04-30 14:49:18.021140000 -0400 |
838 | +++ nfs-utils-1.1.2-kwc/utils/gssd/context_mit.c 2008-04-30 14:49:18.097064000 -0400 | |
0ac65518 | 839 | @@ -1,5 +1,5 @@ |
97cc26d8 | 840 | /* |
0ac65518 JB |
841 | - Copyright (c) 2004 The Regents of the University of Michigan. |
842 | + Copyright (c) 2004-2006 The Regents of the University of Michigan. | |
843 | All rights reserved. | |
97cc26d8 | 844 | |
0ac65518 JB |
845 | Redistribution and use in source and binary forms, with or without |
846 | @@ -36,6 +36,7 @@ | |
847 | #include <stdio.h> | |
848 | #include <syslog.h> | |
849 | #include <string.h> | |
850 | +#include <errno.h> | |
851 | #include <gssapi/gssapi.h> | |
852 | #include <rpc/rpc.h> | |
853 | #include <rpc/auth_gss.h> | |
854 | @@ -50,8 +51,7 @@ | |
855 | /* XXX argggg, there's gotta be a better way than just duplicating this | |
856 | * whole struct. Unfortunately, this is in a "private" header file, | |
857 | * so this is our best choice at this point :-/ | |
858 | - * | |
859 | - * XXX Does this match the Heimdal definition? */ | |
860 | + */ | |
861 | ||
862 | typedef struct _krb5_gss_ctx_id_rec { | |
863 | unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */ | |
12480a97 | 864 | @@ -154,48 +154,120 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss |
97cc26d8 | 865 | { |
0ac65518 JB |
866 | krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id; |
867 | char *p, *end; | |
868 | - static int constant_one = 1; | |
869 | static int constant_zero = 0; | |
870 | + static int constant_one = 1; | |
871 | + static int constant_two = 2; | |
872 | uint32_t word_seq_send; | |
873 | + u_int64_t seq_send_64bit; | |
874 | + uint32_t v2_flags = 0; | |
0ac65518 JB |
875 | |
876 | if (!(buf->value = calloc(1, MAX_CTX_LEN))) | |
877 | goto out_err; | |
878 | p = buf->value; | |
879 | end = buf->value + MAX_CTX_LEN; | |
880 | ||
881 | - if (kctx->initiate) { | |
882 | - if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
883 | - } | |
884 | - else { | |
885 | - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
886 | - } | |
887 | - if (kctx->seed_init) { | |
888 | - if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
889 | - } | |
890 | - else { | |
891 | - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
892 | - } | |
893 | - if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) | |
12480a97 JB |
894 | + switch (kctx->enc->enctype) { |
895 | + case ENCTYPE_DES_CBC_CRC: | |
896 | + case ENCTYPE_DES_CBC_MD4: | |
897 | + case ENCTYPE_DES_CBC_MD5: | |
898 | + case ENCTYPE_DES_CBC_RAW: | |
0ac65518 JB |
899 | + /* Old format of context to the kernel */ |
900 | + if (kctx->initiate) { | |
901 | + if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
902 | + } | |
903 | + else { | |
904 | + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
905 | + } | |
906 | + if (kctx->seed_init) { | |
907 | + if (WRITE_BYTES(&p, end, constant_one)) goto out_err; | |
908 | + } | |
909 | + else { | |
910 | + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; | |
911 | + } | |
912 | + if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) | |
913 | + goto out_err; | |
914 | + if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; | |
915 | + if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; | |
916 | + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; | |
917 | + word_seq_send = kctx->seq_send; | |
918 | + if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; | |
919 | + if (write_oid(&p, end, kctx->mech_used)) goto out_err; | |
920 | + | |
921 | + printerr(2, "serialize_krb5_ctx: serializing keys with " | |
922 | + "enctype %d and length %d\n", | |
923 | + kctx->enc->enctype, kctx->enc->length); | |
924 | + | |
925 | + if (write_keyblock(&p, end, kctx->enc)) goto out_err; | |
926 | + if (write_keyblock(&p, end, kctx->seq)) goto out_err; | |
927 | + break; | |
12480a97 JB |
928 | + case ENCTYPE_DES3_CBC_RAW: |
929 | + case ENCTYPE_DES3_CBC_SHA1: | |
930 | + case ENCTYPE_ARCFOUR_HMAC: | |
931 | + case ENCTYPE_ARCFOUR_HMAC_EXP: | |
932 | + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | |
933 | + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | |
0ac65518 | 934 | + /* New format of context to the kernel */ |
12480a97 | 935 | + /* u32 flags; |
0ac65518 JB |
936 | + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 |
937 | + * #define KRB5_CTX_FLAG_CFX 0x00000002 | |
938 | + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 | |
12480a97 | 939 | + * s32 endtime; |
0ac65518 JB |
940 | + * u64 seq_send; |
941 | + * u32 enctype; | |
12480a97 | 942 | + * rawkey data |
0ac65518 | 943 | + */ |
0ac65518 | 944 | + |
12480a97 JB |
945 | + if (kctx->initiate) |
946 | + v2_flags |= KRB5_CTX_FLAG_INITIATOR; | |
947 | + if (kctx->proto == 1) | |
948 | + v2_flags |= KRB5_CTX_FLAG_CFX; | |
949 | + if (kctx->have_acceptor_subkey) | |
950 | + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; | |
0ac65518 | 951 | + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; |
12480a97 | 952 | + if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; |
0ac65518 JB |
953 | + |
954 | + seq_send_64bit = kctx->seq_send; | |
955 | + if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err; | |
956 | + | |
12480a97 JB |
957 | + if (kctx->have_acceptor_subkey) { |
958 | + if (WRITE_BYTES(&p, end, kctx->acceptor_subkey->enctype)) | |
959 | + goto out_err; | |
960 | + printerr(2, "serialize_krb5_ctx: serializing subkey " | |
961 | + "with enctype %d and size %d\n", | |
962 | + kctx->acceptor_subkey->enctype, | |
963 | + kctx->acceptor_subkey->length); | |
964 | + | |
965 | + if (write_bytes(&p, end, | |
966 | + kctx->acceptor_subkey->contents, | |
967 | + kctx->acceptor_subkey->length)) | |
968 | + goto out_err; | |
969 | + } else { | |
970 | + if (WRITE_BYTES(&p, end, kctx->enc->enctype)) | |
971 | + goto out_err; | |
972 | + printerr(2, "serialize_krb5_ctx: serializing key " | |
973 | + "with enctype %d and size %d\n", | |
974 | + kctx->enc->enctype, kctx->enc->length); | |
975 | + | |
976 | + if (write_bytes(&p, end, kctx->enc->contents, | |
977 | + kctx->enc->length)) | |
978 | + goto out_err; | |
979 | + } | |
0ac65518 JB |
980 | + break; |
981 | + default: | |
12480a97 JB |
982 | + printerr(0, "ERROR: serialize_krb5_ctx: unsupported encryption " |
983 | + "algorithm %d\n", kctx->enc->enctype); | |
0ac65518 JB |
984 | goto out_err; |
985 | - if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; | |
986 | - if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; | |
987 | - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; | |
988 | - word_seq_send = kctx->seq_send; | |
989 | - if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; | |
990 | - if (write_oid(&p, end, kctx->mech_used)) goto out_err; | |
991 | - | |
992 | - printerr(2, "serialize_krb5_ctx: serializing keys with " | |
993 | - "enctype %d and length %d\n", | |
994 | - kctx->enc->enctype, kctx->enc->length); | |
995 | - | |
996 | - if (write_keyblock(&p, end, kctx->enc)) goto out_err; | |
997 | - if (write_keyblock(&p, end, kctx->seq)) goto out_err; | |
998 | + } | |
999 | ||
1000 | buf->length = p - (char *)buf->value; | |
1001 | return 0; | |
1002 | + | |
1003 | out_err: | |
1004 | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); | |
1005 | - if (buf->value) free(buf->value); | |
1006 | + if (buf->value) { | |
1007 | + free(buf->value); | |
1008 | + } | |
1009 | + buf->value = NULL; | |
1010 | buf->length = 0; | |
1011 | return -1; | |
1012 | } | |
12480a97 | 1013 | _ |