X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/08822d99de1b1080f8c730bbebc192b5b45bf89b..77fa2ab46721bcc01b898b7df0aa85c170931c06:/openssh/kexgsss.c?ds=sidebyside diff --git a/openssh/kexgsss.c b/openssh/kexgsss.c index a860409..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) @@ -58,39 +63,46 @@ kexgss_server(Kex *kex) gss_buffer_desc gssbuf, recv_tok, msg_tok; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; Gssctxt *ctxt = NULL; - unsigned int klen, kout, hashlen; - unsigned char *kbuf, *hash; + u_int slen, klen, kout, hashlen; + u_char *kbuf, *hash; DH *dh; int min = -1, max = -1, nbits = -1; BIGNUM *shared_secret = NULL; BIGNUM *dh_client_pub = NULL; int type = 0; - int gex; - u_int slen; 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(); @@ -112,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 { @@ -159,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); } @@ -169,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"); @@ -187,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, @@ -207,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"); @@ -258,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