summaryrefslogtreecommitdiff
path: root/gss-genr.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
committerColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
commitdf03186a4f9e0c2ece398b5c0571cb6263d7a752 (patch)
tree1aab079441dff9615274769b19f2d734ddf508dd /gss-genr.c
parent6ad6994c288662fca6949f42bf91fec2aff00bca (diff)
parent99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (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.c116
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
78char * 78char *
79ssh_gssapi_client_mechanisms(const char *host) { 79ssh_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
89char * 90char *
90ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, 91ssh_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
377OM_uint32 384OM_uint32
385ssh_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
415OM_uint32
378ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 416ssh_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
415int 453int
416ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 454ssh_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
492int
493ssh_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 */