diff options
author | Colin Watson <cjwatson@debian.org> | 2010-01-01 23:53:30 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2010-01-01 23:53:30 +0000 |
commit | df03186a4f9e0c2ece398b5c0571cb6263d7a752 (patch) | |
tree | 1aab079441dff9615274769b19f2d734ddf508dd /gss-genr.c | |
parent | 6ad6994c288662fca6949f42bf91fec2aff00bca (diff) | |
parent | 99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (diff) |
* New upstream release (closes: #536182). Yes, I know 5.3p1 has been out
for a while, but there's no GSSAPI patch available for it yet.
- Change the default cipher order to prefer the AES CTR modes and the
revised "arcfour256" mode to CBC mode ciphers that are susceptible to
CPNI-957037 "Plaintext Recovery Attack Against SSH".
- Add countermeasures to mitigate CPNI-957037-style attacks against the
SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid
packet length or Message Authentication Code, ssh/sshd will continue
reading up to the maximum supported packet length rather than
immediately terminating the connection. This eliminates most of the
known differences in behaviour that leaked information about the
plaintext of injected data which formed the basis of this attack
(closes: #506115, LP: #379329).
- ForceCommand directive now accepts commandline arguments for the
internal-sftp server (closes: #524423, LP: #362511).
- Add AllowAgentForwarding to available Match keywords list (closes:
#540623).
- Make ssh(1) send the correct channel number for
SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to
avoid triggering 'Non-public channel' error messages on sshd(8) in
openssh-5.1.
- Avoid printing 'Non-public channel' warnings in sshd(8), since the
ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a
behaviour introduced in openssh-5.1; closes: #496017).
* Update to GSSAPI patch from
http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch,
including cascading credentials support (LP: #416958).
Diffstat (limited to 'gss-genr.c')
-rw-r--r-- | gss-genr.c | 116 |
1 files changed, 108 insertions, 8 deletions
diff --git a/gss-genr.c b/gss-genr.c index 822a08212..c51fa727d 100644 --- a/gss-genr.c +++ b/gss-genr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker Exp $ */ | 1 | /* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. | 4 | * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. |
5 | * | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions |
@@ -76,19 +76,20 @@ ssh_gssapi_oid_table_ok() { | |||
76 | */ | 76 | */ |
77 | 77 | ||
78 | char * | 78 | char * |
79 | ssh_gssapi_client_mechanisms(const char *host) { | 79 | ssh_gssapi_client_mechanisms(const char *host, const char *client) { |
80 | gss_OID_set gss_supported; | 80 | gss_OID_set gss_supported; |
81 | OM_uint32 min_status; | 81 | OM_uint32 min_status; |
82 | 82 | ||
83 | gss_indicate_mechs(&min_status, &gss_supported); | 83 | if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) |
84 | return NULL; | ||
84 | 85 | ||
85 | return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, | 86 | return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, |
86 | host)); | 87 | host, client)); |
87 | } | 88 | } |
88 | 89 | ||
89 | char * | 90 | char * |
90 | ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | 91 | ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, |
91 | const char *data) { | 92 | const char *host, const char *client) { |
92 | Buffer buf; | 93 | Buffer buf; |
93 | size_t i; | 94 | size_t i; |
94 | int oidpos, enclen; | 95 | int oidpos, enclen; |
@@ -112,7 +113,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, | |||
112 | oidpos = 0; | 113 | oidpos = 0; |
113 | for (i = 0; i < gss_supported->count; i++) { | 114 | for (i = 0; i < gss_supported->count; i++) { |
114 | if (gss_supported->elements[i].length < 128 && | 115 | if (gss_supported->elements[i].length < 128 && |
115 | (*check)(NULL, &(gss_supported->elements[i]), data)) { | 116 | (*check)(NULL, &(gss_supported->elements[i]), host, client)) { |
116 | 117 | ||
117 | deroid[0] = SSH_GSS_OIDTYPE; | 118 | deroid[0] = SSH_GSS_OIDTYPE; |
118 | deroid[1] = gss_supported->elements[i].length; | 119 | deroid[1] = gss_supported->elements[i].length; |
@@ -171,12 +172,18 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { | |||
171 | 172 | ||
172 | switch (kex_type) { | 173 | switch (kex_type) { |
173 | case KEX_GSS_GRP1_SHA1: | 174 | case KEX_GSS_GRP1_SHA1: |
175 | if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) | ||
176 | return GSS_C_NO_OID; | ||
174 | name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; | 177 | name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; |
175 | break; | 178 | break; |
176 | case KEX_GSS_GRP14_SHA1: | 179 | case KEX_GSS_GRP14_SHA1: |
180 | if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) | ||
181 | return GSS_C_NO_OID; | ||
177 | name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; | 182 | name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; |
178 | break; | 183 | break; |
179 | case KEX_GSS_GEX_SHA1: | 184 | case KEX_GSS_GEX_SHA1: |
185 | if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) | ||
186 | return GSS_C_NO_OID; | ||
180 | name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; | 187 | name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; |
181 | break; | 188 | break; |
182 | default: | 189 | default: |
@@ -345,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, | |||
345 | } | 352 | } |
346 | 353 | ||
347 | ctx->major = gss_init_sec_context(&ctx->minor, | 354 | ctx->major = gss_init_sec_context(&ctx->minor, |
348 | GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, | 355 | ctx->client_creds, &ctx->context, ctx->name, ctx->oid, |
349 | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, | 356 | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, |
350 | 0, NULL, recv_tok, NULL, send_tok, flags, NULL); | 357 | 0, NULL, recv_tok, NULL, send_tok, flags, NULL); |
351 | 358 | ||
@@ -375,6 +382,37 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) | |||
375 | } | 382 | } |
376 | 383 | ||
377 | OM_uint32 | 384 | OM_uint32 |
385 | ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) | ||
386 | { | ||
387 | gss_buffer_desc gssbuf; | ||
388 | gss_name_t gssname; | ||
389 | OM_uint32 status; | ||
390 | gss_OID_set oidset; | ||
391 | |||
392 | gssbuf.value = (void *) name; | ||
393 | gssbuf.length = strlen(gssbuf.value); | ||
394 | |||
395 | gss_create_empty_oid_set(&status, &oidset); | ||
396 | gss_add_oid_set_member(&status, ctx->oid, &oidset); | ||
397 | |||
398 | ctx->major = gss_import_name(&ctx->minor, &gssbuf, | ||
399 | GSS_C_NT_USER_NAME, &gssname); | ||
400 | |||
401 | if (!ctx->major) | ||
402 | ctx->major = gss_acquire_cred(&ctx->minor, | ||
403 | gssname, 0, oidset, GSS_C_INITIATE, | ||
404 | &ctx->client_creds, NULL, NULL); | ||
405 | |||
406 | gss_release_name(&status, &gssname); | ||
407 | gss_release_oid_set(&status, &oidset); | ||
408 | |||
409 | if (ctx->major) | ||
410 | ssh_gssapi_error(ctx); | ||
411 | |||
412 | return(ctx->major); | ||
413 | } | ||
414 | |||
415 | OM_uint32 | ||
378 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) | 416 | ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) |
379 | { | 417 | { |
380 | if (ctx == NULL) | 418 | if (ctx == NULL) |
@@ -413,7 +451,8 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, | |||
413 | } | 451 | } |
414 | 452 | ||
415 | int | 453 | int |
416 | ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) | 454 | ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, |
455 | const char *client) | ||
417 | { | 456 | { |
418 | gss_buffer_desc token = GSS_C_EMPTY_BUFFER; | 457 | gss_buffer_desc token = GSS_C_EMPTY_BUFFER; |
419 | OM_uint32 major, minor; | 458 | OM_uint32 major, minor; |
@@ -431,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) | |||
431 | ssh_gssapi_build_ctx(ctx); | 470 | ssh_gssapi_build_ctx(ctx); |
432 | ssh_gssapi_set_oid(*ctx, oid); | 471 | ssh_gssapi_set_oid(*ctx, oid); |
433 | major = ssh_gssapi_import_name(*ctx, host); | 472 | major = ssh_gssapi_import_name(*ctx, host); |
473 | |||
474 | if (!GSS_ERROR(major) && client) | ||
475 | major = ssh_gssapi_client_identity(*ctx, client); | ||
476 | |||
434 | if (!GSS_ERROR(major)) { | 477 | if (!GSS_ERROR(major)) { |
435 | major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, | 478 | major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, |
436 | NULL); | 479 | NULL); |
@@ -446,4 +489,61 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) | |||
446 | return (!GSS_ERROR(major)); | 489 | return (!GSS_ERROR(major)); |
447 | } | 490 | } |
448 | 491 | ||
492 | int | ||
493 | ssh_gssapi_credentials_updated(Gssctxt *ctxt) { | ||
494 | static gss_name_t saved_name = GSS_C_NO_NAME; | ||
495 | static OM_uint32 saved_lifetime = 0; | ||
496 | static gss_OID saved_mech = GSS_C_NO_OID; | ||
497 | static gss_name_t name; | ||
498 | static OM_uint32 last_call = 0; | ||
499 | OM_uint32 lifetime, now, major, minor; | ||
500 | int equal; | ||
501 | gss_cred_usage_t usage = GSS_C_INITIATE; | ||
502 | |||
503 | now = time(NULL); | ||
504 | |||
505 | if (ctxt) { | ||
506 | debug("Rekey has happened - updating saved versions"); | ||
507 | |||
508 | if (saved_name != GSS_C_NO_NAME) | ||
509 | gss_release_name(&minor, &saved_name); | ||
510 | |||
511 | major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, | ||
512 | &saved_name, &saved_lifetime, NULL, NULL); | ||
513 | |||
514 | if (!GSS_ERROR(major)) { | ||
515 | saved_mech = ctxt->oid; | ||
516 | saved_lifetime+= now; | ||
517 | } else { | ||
518 | /* Handle the error */ | ||
519 | } | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | if (now - last_call < 10) | ||
524 | return 0; | ||
525 | |||
526 | last_call = now; | ||
527 | |||
528 | if (saved_mech == GSS_C_NO_OID) | ||
529 | return 0; | ||
530 | |||
531 | major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, | ||
532 | &name, &lifetime, NULL, NULL); | ||
533 | if (major == GSS_S_CREDENTIALS_EXPIRED) | ||
534 | return 0; | ||
535 | else if (GSS_ERROR(major)) | ||
536 | return 0; | ||
537 | |||
538 | major = gss_compare_name(&minor, saved_name, name, &equal); | ||
539 | gss_release_name(&minor, &name); | ||
540 | if (GSS_ERROR(major)) | ||
541 | return 0; | ||
542 | |||
543 | if (equal && (saved_lifetime < lifetime + now - 10)) | ||
544 | return 1; | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
449 | #endif /* GSSAPI */ | 549 | #endif /* GSSAPI */ |