X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/f472818dbd4776623983e221752ec18aa17afe85..4e1c687b22bf2e4eb8d3549081a1f468eb13e374:/openssh/kexgsss.c diff --git a/openssh/kexgsss.c b/openssh/kexgsss.c index 4e93cb8..3e5205c 100644 --- a/openssh/kexgsss.c +++ b/openssh/kexgsss.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,21 +26,26 @@ #ifdef GSSAPI +#include + #include #include #include "xmalloc.h" #include "buffer.h" -#include "bufaux.h" +#include "ssh2.h" +#include "key.h" +#include "cipher.h" #include "kex.h" #include "log.h" #include "packet.h" #include "dh.h" -#include "ssh2.h" #include "ssh-gss.h" #include "monitor_wrap.h" +#include "servconf.h" static void kex_gss_send_error(Gssctxt *ctxt); +extern ServerOptions options; void kexgss_server(Kex *kex) @@ -65,31 +70,39 @@ kexgss_server(Kex *kex) BIGNUM *shared_secret = NULL; BIGNUM *dh_client_pub = NULL; int type = 0; - int gex; gss_OID oid; - + char *mechs; + /* Initialise GSSAPI */ /* If we're rekeying, privsep means that some of the private structures * in the GSSAPI code are no longer available. This kludges them back - * into life + * into life */ if (!ssh_gssapi_oid_table_ok()) - ssh_gssapi_server_mechanisms(); + if ((mechs = ssh_gssapi_server_mechanisms())) + xfree(mechs); debug2("%s: Identifying %s", __func__, kex->name); - oid = ssh_gssapi_id_kex(NULL, kex->name, &gex); - if (oid == NULL) + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) fatal("Unknown gssapi mechanism"); debug2("%s: Acquiring credentials", __func__); if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) { kex_gss_send_error(ctxt); - fatal("Unable to acquire credentials for the server"); - } - - if (gex) { + fatal("Unable to acquire credentials for the server"); + } + + switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + dh = dh_new_group1(); + break; + case KEX_GSS_GRP14_SHA1: + dh = dh_new_group14(); + break; + case KEX_GSS_GEX_SHA1: debug("Doing group exchange"); packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); min = packet_get_int(); @@ -111,10 +124,11 @@ kexgss_server(Kex *kex) packet_send(); packet_write_wait(); - - } else { - dh = dh_new_group1(); + break; + default: + fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); } + dh_gen_key(dh, kex->we_need * 8); do { @@ -158,7 +172,7 @@ kexgss_server(Kex *kex) if (maj_status & GSS_S_CONTINUE_NEEDED) { debug("Sending GSSAPI_CONTINUE"); packet_start(SSH2_MSG_KEXGSS_CONTINUE); - packet_put_string(send_tok.value, send_tok.length); + packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); gss_release_buffer(&min_status, &send_tok); } @@ -168,7 +182,7 @@ kexgss_server(Kex *kex) kex_gss_send_error(ctxt); if (send_tok.length > 0) { packet_start(SSH2_MSG_KEXGSS_CONTINUE); - packet_put_string(send_tok.value, send_tok.length); + packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); } packet_disconnect("GSSAPI Key Exchange handshake failed"); @@ -186,13 +200,32 @@ kexgss_server(Kex *kex) klen = DH_size(dh); kbuf = xmalloc(klen); kout = DH_compute_key(kbuf, dh_client_pub, dh); + if (kout < 0) + fatal("DH_compute_key: failed"); shared_secret = BN_new(); - BN_bin2bn(kbuf, kout, shared_secret); + if (shared_secret == NULL) + fatal("kexgss_server: BN_new failed"); + + if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) + fatal("kexgss_server: BN_bin2bn failed"); + memset(kbuf, 0, klen); xfree(kbuf); - if (gex) { + switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: + kex_dh_hash( + kex->client_version_string, kex->server_version_string, + buffer_ptr(&kex->peer), buffer_len(&kex->peer), + buffer_ptr(&kex->my), buffer_len(&kex->my), + NULL, 0, /* Change this if we start sending host keys */ + dh_client_pub, dh->pub_key, shared_secret, + &hash, &hashlen + ); + break; + case KEX_GSS_GEX_SHA1: kexgex_hash( kex->evp_md, kex->client_version_string, kex->server_version_string, @@ -206,28 +239,21 @@ kexgss_server(Kex *kex) shared_secret, &hash, &hashlen ); + break; + default: + fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); } - else { - /* The GSSAPI hash is identical to the Diffie Helman one */ - kex_dh_hash( - kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), - NULL, 0, /* Change this if we start sending host keys */ - dh_client_pub, dh->pub_key, shared_secret, - &hash, &hashlen - ); - } - BN_free(dh_client_pub); + + BN_clear_free(dh_client_pub); if (kex->session_id == NULL) { - kex->session_id_len = 20; + kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } gssbuf.value = hash; - gssbuf.length = 20; /* Hashlen appears to always be 20 */ + gssbuf.length = hashlen; if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) fatal("Couldn't get MIC"); @@ -257,6 +283,11 @@ kexgss_server(Kex *kex) kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); } static void