]>
Commit | Line | Data |
---|---|---|
5598e598 | 1 | /* |
b59afbfe | 2 | * Copyright (c) 2001,2002 Simon Wilkinson. All rights reserved. |
5598e598 | 3 | * |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
15 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
16 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
19 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
20 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
23 | */ | |
24 | ||
25 | #include "includes.h" | |
26 | ||
27 | #ifdef GSSAPI | |
28 | ||
29 | #include "ssh.h" | |
6a8bca29 | 30 | #include "ssh1.h" |
5598e598 | 31 | #include "ssh2.h" |
32 | #include "xmalloc.h" | |
33 | #include "buffer.h" | |
34 | #include "bufaux.h" | |
35 | #include "packet.h" | |
36 | #include "compat.h" | |
37 | #include <openssl/evp.h> | |
38 | #include "cipher.h" | |
39 | #include "kex.h" | |
40 | #include "auth.h" | |
41 | #include "log.h" | |
e5affddc | 42 | #include "channels.h" |
5598e598 | 43 | #include "session.h" |
44 | #include "dispatch.h" | |
45 | #include "servconf.h" | |
905081a4 | 46 | #include "compat.h" |
510132b6 | 47 | #include "misc.h" |
b59afbfe | 48 | #include "monitor_wrap.h" |
5598e598 | 49 | |
50 | #include "ssh-gss.h" | |
51 | ||
52 | extern ServerOptions options; | |
53 | extern u_char *session_id2; | |
54 | extern int session_id2_len; | |
55 | ||
5598e598 | 56 | typedef struct ssh_gssapi_cred_cache { |
57 | char *filename; | |
58 | char *envvar; | |
59 | char *envval; | |
60 | void *data; | |
61 | } ssh_gssapi_cred_cache; | |
62 | ||
63 | static struct ssh_gssapi_cred_cache gssapi_cred_store = {NULL,NULL,NULL}; | |
6a8bca29 | 64 | |
65 | /* | |
66 | * Environment variables pointing to delegated credentials | |
67 | */ | |
68 | static char *delegation_env[] = { | |
69 | "X509_USER_PROXY", /* GSSAPI/SSLeay */ | |
70 | "KRB5CCNAME", /* Krb5 and possibly SSLeay */ | |
71 | NULL | |
72 | }; | |
5598e598 | 73 | |
b59afbfe | 74 | static void gssapi_unsetenv(const char *var); |
44a053a3 | 75 | |
5598e598 | 76 | #ifdef KRB5 |
77 | ||
78 | #ifdef HEIMDAL | |
79 | #include <krb5.h> | |
80 | #else | |
81 | #include <gssapi_krb5.h> | |
82 | #define krb5_get_err_text(context,code) error_message(code) | |
83 | #endif | |
84 | ||
85 | static krb5_context krb_context = NULL; | |
86 | ||
87 | /* Initialise the krb5 library, so we can use it for those bits that | |
88 | * GSSAPI won't do */ | |
89 | ||
90 | int ssh_gssapi_krb5_init() { | |
91 | krb5_error_code problem; | |
92 | ||
93 | if (krb_context !=NULL) | |
94 | return 1; | |
95 | ||
96 | problem = krb5_init_context(&krb_context); | |
97 | if (problem) { | |
98 | log("Cannot initialize krb5 context"); | |
99 | return 0; | |
100 | } | |
101 | krb5_init_ets(krb_context); | |
102 | ||
103 | return 1; | |
104 | } | |
105 | ||
106 | /* Check if this user is OK to login. This only works with krb5 - other | |
107 | * GSSAPI mechanisms will need their own. | |
108 | * Returns true if the user is OK to log in, otherwise returns 0 | |
109 | */ | |
110 | ||
111 | int | |
112 | ssh_gssapi_krb5_userok(char *name) { | |
113 | krb5_principal princ; | |
114 | int retval; | |
115 | ||
116 | if (ssh_gssapi_krb5_init() == 0) | |
117 | return 0; | |
118 | ||
119 | if ((retval=krb5_parse_name(krb_context, gssapi_client_name.value, | |
120 | &princ))) { | |
121 | log("krb5_parse_name(): %.100s", | |
122 | krb5_get_err_text(krb_context,retval)); | |
123 | return 0; | |
124 | } | |
125 | if (krb5_kuserok(krb_context, princ, name)) { | |
126 | retval = 1; | |
127 | log("Authorized to %s, krb5 principal %s (krb5_kuserok)",name, | |
128 | (char *)gssapi_client_name.value); | |
129 | } | |
130 | else | |
131 | retval = 0; | |
132 | ||
133 | krb5_free_principal(krb_context, princ); | |
134 | return retval; | |
135 | } | |
b59afbfe | 136 | |
137 | int | |
138 | ssh_gssapi_krb5_localname(char **user) | |
139 | { | |
140 | krb5_principal princ; | |
141 | ||
54425c7a | 142 | if (ssh_gssapi_krb5_init() == 0) |
143 | return 0; | |
144 | ||
b59afbfe | 145 | if (krb5_parse_name(krb_context, gssapi_client_name.value, &princ)) { |
146 | return(0); | |
147 | } | |
148 | *user = (char *)xmalloc(256); | |
149 | if (krb5_aname_to_localname(krb_context, princ, 256, *user)) { | |
150 | xfree(*user); | |
151 | *user = NULL; | |
152 | return(0); | |
153 | } | |
154 | return(1); | |
155 | } | |
5598e598 | 156 | |
157 | /* Make sure that this is called _after_ we've setuid to the user */ | |
158 | ||
159 | /* This writes out any forwarded credentials. Its specific to the Kerberos | |
160 | * GSSAPI mechanism | |
161 | * | |
162 | * We assume that our caller has made sure that the user has selected | |
163 | * delegated credentials, and that the client_creds structure is correctly | |
164 | * populated. | |
165 | */ | |
166 | ||
c4571a29 | 167 | OM_uint32 |
54425c7a | 168 | ssh_gssapi_krb5_storecreds(gss_buffer_t export_buffer) { |
5598e598 | 169 | krb5_ccache ccache; |
170 | krb5_error_code problem; | |
171 | krb5_principal princ; | |
172 | char ccname[35]; | |
173 | static char name[40]; | |
174 | int tmpfd; | |
175 | OM_uint32 maj_status,min_status; | |
54425c7a | 176 | gss_cred_id_t krb5_cred_handle; |
5598e598 | 177 | |
178 | ||
179 | if (gssapi_client_creds==NULL) { | |
180 | debug("No credentials stored"); | |
c4571a29 | 181 | return GSS_S_NO_CRED; |
5598e598 | 182 | } |
183 | ||
184 | if (ssh_gssapi_krb5_init() == 0) | |
c4571a29 | 185 | return GSS_S_FAILURE; |
5598e598 | 186 | |
187 | if (options.gss_use_session_ccache) { | |
188 | snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d_XXXXXX",geteuid()); | |
189 | ||
190 | if ((tmpfd = mkstemp(ccname))==-1) { | |
191 | log("mkstemp(): %.100s", strerror(errno)); | |
c4571a29 | 192 | return GSS_S_FAILURE; |
5598e598 | 193 | } |
194 | if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) { | |
195 | log("fchmod(): %.100s", strerror(errno)); | |
196 | close(tmpfd); | |
c4571a29 | 197 | return GSS_S_FAILURE; |
5598e598 | 198 | } |
199 | } else { | |
200 | snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d",geteuid()); | |
201 | tmpfd = open(ccname, O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); | |
202 | if (tmpfd == -1) { | |
203 | log("open(): %.100s", strerror(errno)); | |
c4571a29 | 204 | return GSS_S_FAILURE; |
5598e598 | 205 | } |
206 | } | |
207 | ||
208 | close(tmpfd); | |
209 | snprintf(name, sizeof(name), "FILE:%s",ccname); | |
210 | ||
211 | if ((problem = krb5_cc_resolve(krb_context, name, &ccache))) { | |
212 | log("krb5_cc_default(): %.100s", | |
213 | krb5_get_err_text(krb_context,problem)); | |
c4571a29 | 214 | return GSS_S_FAILURE; |
5598e598 | 215 | } |
216 | ||
217 | if ((problem = krb5_parse_name(krb_context, gssapi_client_name.value, | |
218 | &princ))) { | |
219 | log("krb5_parse_name(): %.100s", | |
220 | krb5_get_err_text(krb_context,problem)); | |
221 | krb5_cc_destroy(krb_context,ccache); | |
c4571a29 | 222 | return GSS_S_FAILURE; |
5598e598 | 223 | } |
224 | ||
225 | if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { | |
226 | log("krb5_cc_initialize(): %.100s", | |
227 | krb5_get_err_text(krb_context,problem)); | |
228 | krb5_free_principal(krb_context,princ); | |
229 | krb5_cc_destroy(krb_context,ccache); | |
c4571a29 | 230 | return GSS_S_FAILURE; |
5598e598 | 231 | } |
232 | ||
233 | krb5_free_principal(krb_context,princ); | |
234 | ||
54425c7a | 235 | #ifdef MECHGLUE |
236 | krb5_cred_handle = | |
237 | __gss_get_mechanism_cred(gssapi_client_creds, | |
238 | &(supported_mechs[GSS_KERBEROS].oid)); | |
239 | #else | |
240 | krb5_cred_handle = gssapi_client_creds; | |
241 | #endif | |
242 | ||
5598e598 | 243 | if ((maj_status = gss_krb5_copy_ccache(&min_status, |
54425c7a | 244 | krb5_cred_handle, |
5598e598 | 245 | ccache))) { |
246 | log("gss_krb5_copy_ccache() failed"); | |
6f9f4dab | 247 | ssh_gssapi_error(&supported_mechs[GSS_KERBEROS].oid, |
248 | maj_status,min_status); | |
5598e598 | 249 | krb5_cc_destroy(krb_context,ccache); |
8331b5e4 | 250 | return GSS_S_FAILURE; |
5598e598 | 251 | } |
5598e598 | 252 | |
253 | krb5_cc_close(krb_context,ccache); | |
254 | ||
54425c7a | 255 | export_buffer->length = strlen("KRB5CCNAME")+strlen(name)+1; |
256 | export_buffer->value = xmalloc(export_buffer->length+1); | |
257 | sprintf(export_buffer->value, "%s=%s", "KRB5CCNAME", name); | |
5598e598 | 258 | |
c4571a29 | 259 | return GSS_S_COMPLETE; |
5598e598 | 260 | } |
261 | ||
262 | #endif /* KRB5 */ | |
263 | ||
264 | #ifdef GSI | |
265 | #include <globus_gss_assist.h> | |
266 | ||
267 | /* | |
268 | * Check if this user is OK to login under GSI. User has been authenticated | |
269 | * as identity in global 'client_name.value' and is trying to log in as passed | |
270 | * username in 'name'. | |
271 | * | |
272 | * Returns non-zero if user is authorized, 0 otherwise. | |
273 | */ | |
274 | int | |
275 | ssh_gssapi_gsi_userok(char *name) | |
276 | { | |
277 | int authorized = 0; | |
278 | ||
279 | /* This returns 0 on success */ | |
280 | authorized = (globus_gss_assist_userok(gssapi_client_name.value, | |
281 | name) == 0); | |
282 | ||
59e1d8e0 | 283 | log("GSI user %s is%s authorized as target user %s", |
284 | (char *) gssapi_client_name.value, (authorized ? "" : " not"), name); | |
5598e598 | 285 | |
286 | return authorized; | |
287 | } | |
288 | ||
b59afbfe | 289 | /* |
290 | * Return the local username associated with the GSI credentials. | |
291 | */ | |
292 | int | |
293 | ssh_gssapi_gsi_localname(char **user) | |
294 | { | |
295 | return(globus_gss_assist_gridmap(gssapi_client_name.value, user) == 0); | |
296 | } | |
297 | ||
5598e598 | 298 | /* |
299 | * Handle setting up child environment for GSI. | |
300 | * | |
301 | * Make sure that this is called _after_ we've setuid to the user. | |
302 | */ | |
c4571a29 | 303 | OM_uint32 |
54425c7a | 304 | ssh_gssapi_gsi_storecreds(gss_buffer_t export_buffer) |
5598e598 | 305 | { |
306 | OM_uint32 major_status; | |
307 | OM_uint32 minor_status; | |
c4571a29 | 308 | |
5598e598 | 309 | if (gssapi_client_creds != NULL) |
310 | { | |
311 | char *creds_env = NULL; | |
312 | ||
313 | /* | |
314 | * This is the current hack with the GSI gssapi library to | |
315 | * export credentials to disk. | |
316 | */ | |
317 | ||
318 | debug("Exporting delegated credentials"); | |
319 | ||
320 | minor_status = 0xdee0; /* Magic value */ | |
321 | major_status = | |
322 | gss_inquire_cred(&minor_status, | |
323 | gssapi_client_creds, | |
324 | (gss_name_t *) &creds_env, | |
325 | NULL, | |
326 | NULL, | |
327 | NULL); | |
328 | ||
329 | if ((major_status == GSS_S_COMPLETE) && | |
330 | (minor_status == 0xdee1) && | |
331 | (creds_env != NULL)) | |
332 | { | |
333 | char *value; | |
334 | ||
335 | /* | |
336 | * String is of the form: | |
337 | * X509_USER_DELEG_PROXY=filename | |
338 | * so we parse out the filename | |
339 | * and then set X509_USER_PROXY | |
340 | * to point at it. | |
341 | */ | |
342 | value = strchr(creds_env, '='); | |
343 | ||
344 | if (value != NULL) | |
345 | { | |
346 | *value = '\0'; | |
347 | value++; | |
54425c7a | 348 | export_buffer->length= |
349 | strlen("X509_USER_PROXY")+strlen(value)+1; | |
350 | export_buffer->value = | |
351 | xmalloc(export_buffer->length+1); | |
352 | sprintf(export_buffer->value, "%s=%s", | |
353 | "X509_USER_PROXY", value); | |
354 | ||
c4571a29 | 355 | return GSS_S_COMPLETE; |
5598e598 | 356 | } |
357 | else | |
358 | { | |
359 | log("Failed to parse delegated credentials string '%s'", | |
360 | creds_env); | |
361 | } | |
362 | } | |
363 | else | |
364 | { | |
365 | log("Failed to export delegated credentials (error %ld)", | |
366 | major_status); | |
367 | } | |
8331b5e4 | 368 | } |
369 | return 0; | |
5598e598 | 370 | } |
371 | ||
372 | #endif /* GSI */ | |
373 | ||
374 | void | |
375 | ssh_gssapi_cleanup_creds(void *ignored) | |
376 | { | |
c4571a29 | 377 | /* OM_uint32 min_stat; */ |
378 | ||
5598e598 | 379 | if (gssapi_cred_store.filename!=NULL) { |
380 | /* Unlink probably isn't sufficient */ | |
c81b5eba | 381 | debug("removing gssapi cred file \"%s\"",gssapi_cred_store.filename); |
5598e598 | 382 | unlink(gssapi_cred_store.filename); |
383 | } | |
c4571a29 | 384 | /* DK ?? |
385 | if (gssapi_client_creds != GSS_C_NO_CREDENTIAL) | |
386 | gss_release_cred(&min_stat, &gssapi_client_creds); | |
387 | */ | |
5598e598 | 388 | } |
389 | ||
c4571a29 | 390 | OM_uint32 |
54425c7a | 391 | ssh_gssapi_export_cred(OM_uint32 * minor_status, |
392 | const gss_cred_id_t cred_handle, | |
393 | const gss_OID desired_mech, | |
394 | OM_uint32 option_req, | |
395 | gss_buffer_t export_buffer) | |
5598e598 | 396 | { |
c4571a29 | 397 | OM_uint32 maj_stat = GSS_S_FAILURE; |
398 | ||
54425c7a | 399 | if (option_req != 1) return GSS_S_UNAVAILABLE; |
400 | if (desired_mech != NULL) return GSS_S_BAD_MECH; | |
401 | ||
5598e598 | 402 | switch (gssapi_client_type) { |
403 | #ifdef KRB5 | |
404 | case GSS_KERBEROS: | |
54425c7a | 405 | maj_stat = ssh_gssapi_krb5_storecreds(export_buffer); |
5598e598 | 406 | break; |
407 | #endif | |
408 | #ifdef GSI | |
409 | case GSS_GSI: | |
54425c7a | 410 | maj_stat = ssh_gssapi_gsi_storecreds(export_buffer); |
5598e598 | 411 | break; |
412 | #endif /* GSI */ | |
413 | case GSS_LAST_ENTRY: | |
414 | /* GSSAPI not used in this authentication */ | |
415 | debug("No GSSAPI credentials stored"); | |
416 | break; | |
417 | default: | |
418 | log("ssh_gssapi_do_child: Unknown mechanism"); | |
419 | ||
420 | } | |
c4571a29 | 421 | |
422 | if (GSS_ERROR(maj_stat)) { | |
423 | *minor_status = GSS_S_FAILURE; | |
c4571a29 | 424 | } |
54425c7a | 425 | return maj_stat; |
c4571a29 | 426 | } |
c4571a29 | 427 | |
428 | void | |
429 | ssh_gssapi_storecreds() | |
430 | { | |
431 | OM_uint32 maj_stat, min_stat; | |
432 | gss_buffer_desc export_cred = GSS_C_EMPTY_BUFFER; | |
433 | char *p; | |
434 | ||
435 | if (gssapi_client_creds == GSS_C_NO_CREDENTIAL) | |
436 | return; | |
437 | ||
54425c7a | 438 | #ifdef HAVE_GSSAPI_EXT |
c4571a29 | 439 | maj_stat = gss_export_cred(&min_stat, gssapi_client_creds, |
440 | GSS_C_NO_OID, 1, &export_cred); | |
54425c7a | 441 | if (GSS_ERROR(maj_stat) && maj_stat != GSS_S_UNAVAILABLE) { |
6f9f4dab | 442 | ssh_gssapi_error(GSS_C_NO_OID, maj_stat, min_stat); |
c4571a29 | 443 | return; |
444 | } | |
54425c7a | 445 | #endif |
446 | ||
447 | /* If gss_export_cred() is not available, use old methods */ | |
448 | if (export_cred.length == 0) { | |
449 | ssh_gssapi_export_cred(&min_stat, gssapi_client_creds, | |
450 | GSS_C_NO_OID, 1, &export_cred); | |
451 | if (GSS_ERROR(maj_stat)) { | |
6f9f4dab | 452 | ssh_gssapi_error(GSS_C_NO_OID, maj_stat, min_stat); |
54425c7a | 453 | } |
454 | } | |
c4571a29 | 455 | |
456 | p = strchr((char *) export_cred.value, '='); | |
457 | if (p == NULL) { | |
458 | log("Failed to parse exported credentials string '%.100s'", | |
459 | (char *)export_cred.value); | |
460 | gss_release_buffer(&min_stat, &export_cred); | |
461 | return; | |
462 | } | |
463 | *p++ = '\0'; | |
7b5a625b | 464 | #ifdef GSI |
465 | if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) | |
466 | gssapi_cred_store.envvar = strdup("X509_USER_PROXY"); | |
467 | else | |
468 | #endif | |
c4571a29 | 469 | gssapi_cred_store.envvar = strdup((char *)export_cred.value); |
470 | gssapi_cred_store.envval = strdup(p); | |
54425c7a | 471 | #ifdef USE_PAM |
472 | do_pam_putenv(gssapi_cred_store.envvar, gssapi_cred_store.envval); | |
473 | #endif | |
474 | if (strncmp(p, "FILE:", 5) == 0) { | |
475 | p += 5; | |
476 | } | |
c81b5eba | 477 | if (access(p, R_OK) == 0) { |
54425c7a | 478 | gssapi_cred_store.filename = strdup(p); |
479 | } | |
c4571a29 | 480 | gss_release_buffer(&min_stat, &export_cred); |
481 | ||
5598e598 | 482 | if (options.gss_cleanup_creds) { |
483 | fatal_add_cleanup(ssh_gssapi_cleanup_creds, NULL); | |
484 | } | |
5598e598 | 485 | } |
486 | ||
487 | /* This allows GSSAPI methods to do things to the childs environment based | |
488 | * on the passed authentication process and credentials. | |
489 | * | |
490 | * Question: If we didn't use userauth_external for some reason, should we | |
491 | * still delegate credentials? | |
492 | */ | |
493 | void | |
494 | ssh_gssapi_do_child(char ***envp, u_int *envsizep) | |
495 | { | |
496 | ||
497 | if (gssapi_cred_store.envvar!=NULL && | |
498 | gssapi_cred_store.envval!=NULL) { | |
499 | ||
500 | debug("Setting %s to %s", gssapi_cred_store.envvar, | |
501 | gssapi_cred_store.envval); | |
502 | child_set_env(envp, envsizep, gssapi_cred_store.envvar, | |
503 | gssapi_cred_store.envval); | |
504 | } | |
505 | ||
506 | switch(gssapi_client_type) { | |
507 | #ifdef KRB5 | |
508 | case GSS_KERBEROS: break; | |
509 | #endif | |
510 | #ifdef GSI | |
511 | case GSS_GSI: break; | |
512 | #endif | |
513 | case GSS_LAST_ENTRY: | |
514 | debug("No GSSAPI credentials stored"); | |
905081a4 | 515 | break; |
5598e598 | 516 | default: |
517 | log("ssh_gssapi_do_child: Unknown mechanism"); | |
518 | } | |
519 | } | |
520 | ||
521 | int | |
522 | ssh_gssapi_userok(char *user) | |
523 | { | |
524 | if (gssapi_client_name.length==0 || | |
525 | gssapi_client_name.value==NULL) { | |
526 | debug("No suitable client data"); | |
527 | return 0; | |
528 | } | |
529 | switch (gssapi_client_type) { | |
530 | #ifdef KRB5 | |
531 | case GSS_KERBEROS: | |
532 | return(ssh_gssapi_krb5_userok(user)); | |
533 | break; /* Not reached */ | |
534 | #endif | |
535 | #ifdef GSI | |
536 | case GSS_GSI: | |
537 | return(ssh_gssapi_gsi_userok(user)); | |
538 | break; /* Not reached */ | |
539 | #endif /* GSI */ | |
540 | case GSS_LAST_ENTRY: | |
541 | debug("Client not GSSAPI"); | |
542 | break; | |
543 | default: | |
544 | debug("Unknown client authentication type"); | |
545 | } | |
546 | return(0); | |
547 | } | |
548 | ||
549 | int | |
b59afbfe | 550 | ssh_gssapi_localname(char **user) |
5598e598 | 551 | { |
b59afbfe | 552 | *user = NULL; |
553 | if (gssapi_client_name.length==0 || | |
554 | gssapi_client_name.value==NULL) { | |
555 | debug("No suitable client data"); | |
556 | return(0);; | |
5598e598 | 557 | } |
b59afbfe | 558 | switch (gssapi_client_type) { |
559 | #ifdef KRB5 | |
560 | case GSS_KERBEROS: | |
561 | return(ssh_gssapi_krb5_localname(user)); | |
562 | break; /* Not reached */ | |
563 | #endif | |
564 | #ifdef GSI | |
565 | case GSS_GSI: | |
566 | return(ssh_gssapi_gsi_localname(user)); | |
567 | break; /* Not reached */ | |
568 | #endif /* GSI */ | |
569 | case GSS_LAST_ENTRY: | |
570 | debug("Client not GSSAPI"); | |
571 | break; | |
572 | default: | |
573 | debug("Unknown client authentication type"); | |
6a8bca29 | 574 | } |
b59afbfe | 575 | return(0); |
5598e598 | 576 | } |
577 | ||
6a8bca29 | 578 | /* |
579 | * Clean our environment on startup. This means removing any environment | |
580 | * strings that might inadvertantly been in root's environment and | |
581 | * could cause serious security problems if we think we set them. | |
582 | */ | |
583 | void | |
c7221eee | 584 | ssh_gssapi_clean_env(void) |
6a8bca29 | 585 | { |
586 | char *envstr; | |
587 | int envstr_index; | |
588 | ||
589 | ||
590 | for (envstr_index = 0; | |
591 | (envstr = delegation_env[envstr_index]) != NULL; | |
592 | envstr_index++) { | |
593 | ||
594 | if (getenv(envstr)) { | |
595 | debug("Clearing environment variable %s", envstr); | |
596 | gssapi_unsetenv(envstr); | |
597 | } | |
598 | } | |
599 | } | |
600 | ||
601 | /* | |
602 | * Wrapper around unsetenv. | |
603 | */ | |
604 | static void | |
605 | gssapi_unsetenv(const char *var) | |
606 | { | |
607 | #ifdef HAVE_UNSETENV | |
608 | unsetenv(var); | |
609 | ||
610 | #else /* !HAVE_UNSETENV */ | |
611 | extern char **environ; | |
612 | char **p1 = environ; /* New array list */ | |
613 | char **p2 = environ; /* Current array list */ | |
614 | int len = strlen(var); | |
615 | ||
616 | /* | |
617 | * Walk through current environ array (p2) copying each pointer | |
618 | * to new environ array (p1) unless the pointer is to the item | |
619 | * we want to delete. Copy happens in place. | |
620 | */ | |
621 | while (*p2) { | |
622 | if ((strncmp(*p2, var, len) == 0) && | |
623 | ((*p2)[len] == '=')) { | |
624 | /* | |
625 | * *p2 points at item to be deleted, just skip over it | |
626 | */ | |
627 | p2++; | |
628 | } else { | |
629 | /* | |
630 | * *p2 points at item we want to save, so copy it | |
631 | */ | |
632 | *p1 = *p2; | |
633 | p1++; | |
634 | p2++; | |
635 | } | |
636 | } | |
637 | ||
638 | /* And make sure new array is NULL terminated */ | |
639 | *p1 = NULL; | |
640 | #endif /* HAVE_UNSETENV */ | |
641 | } | |
642 | ||
5598e598 | 643 | #endif /* GSSAPI */ |