1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 01:18:00 +00:00
putty-source/ssh/transient-hostkey-cache.c
Simon Tatham 83fa43497f Move the SSH implementation into its own subdirectory.
This clears up another large pile of clutter at the top level, and in
the process, allows me to rename source files to things that don't all
have that annoying 'ssh' prefix at the top.
2021-04-22 18:09:13 +01:00

127 lines
4.0 KiB
C

/*
* Data structure managing host keys in sessions based on GSSAPI KEX.
*
* In a session we started with a GSSAPI key exchange, the concept of
* 'host key' has completely different lifetime and security semantics
* from the usual ones. Per RFC 4462 section 2.1, we assume that any
* host key delivered to us in the course of a GSSAPI key exchange is
* _solely_ there to use as a transient fallback within the same
* session, if at the time of a subsequent rekey the GSS credentials
* are temporarily invalid and so a non-GSS KEX method has to be used.
*
* In particular, in a GSS-based SSH deployment, host keys may not
* even _be_ persistent identities for the server; it would be
* legitimate for a server to generate a fresh one routinely if it
* wanted to, like SSH-1 server keys.
*
* So, in this mode, we never touch the persistent host key cache at
* all, either to check keys against it _or_ to store keys in it.
* Instead, we maintain an in-memory cache of host keys that have been
* mentioned in GSS key exchanges within this particular session, and
* we permit precisely those host keys in non-GSS rekeys.
*/
#include <assert.h>
#include "putty.h"
#include "ssh.h"
struct ssh_transient_hostkey_cache {
tree234 *cache;
};
struct ssh_transient_hostkey_cache_entry {
const ssh_keyalg *alg;
strbuf *pub_blob;
};
static int ssh_transient_hostkey_cache_cmp(void *av, void *bv)
{
const struct ssh_transient_hostkey_cache_entry
*a = (const struct ssh_transient_hostkey_cache_entry *)av,
*b = (const struct ssh_transient_hostkey_cache_entry *)bv;
return strcmp(a->alg->ssh_id, b->alg->ssh_id);
}
static int ssh_transient_hostkey_cache_find(void *av, void *bv)
{
const ssh_keyalg *aalg = (const ssh_keyalg *)av;
const struct ssh_transient_hostkey_cache_entry
*b = (const struct ssh_transient_hostkey_cache_entry *)bv;
return strcmp(aalg->ssh_id, b->alg->ssh_id);
}
ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void)
{
ssh_transient_hostkey_cache *thc = snew(ssh_transient_hostkey_cache);
thc->cache = newtree234(ssh_transient_hostkey_cache_cmp);
return thc;
}
void ssh_transient_hostkey_cache_free(ssh_transient_hostkey_cache *thc)
{
struct ssh_transient_hostkey_cache_entry *ent;
while ((ent = delpos234(thc->cache, 0)) != NULL) {
strbuf_free(ent->pub_blob);
sfree(ent);
}
freetree234(thc->cache);
sfree(thc);
}
void ssh_transient_hostkey_cache_add(
ssh_transient_hostkey_cache *thc, ssh_key *key)
{
struct ssh_transient_hostkey_cache_entry *ent, *retd;
if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
ssh_transient_hostkey_cache_find)) != NULL) {
del234(thc->cache, ent);
strbuf_free(ent->pub_blob);
sfree(ent);
}
ent = snew(struct ssh_transient_hostkey_cache_entry);
ent->alg = ssh_key_alg(key);
ent->pub_blob = strbuf_new();
ssh_key_public_blob(key, BinarySink_UPCAST(ent->pub_blob));
retd = add234(thc->cache, ent);
assert(retd == ent);
}
bool ssh_transient_hostkey_cache_verify(
ssh_transient_hostkey_cache *thc, ssh_key *key)
{
struct ssh_transient_hostkey_cache_entry *ent;
bool toret = false;
if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
ssh_transient_hostkey_cache_find)) != NULL) {
strbuf *this_blob = strbuf_new();
ssh_key_public_blob(key, BinarySink_UPCAST(this_blob));
if (this_blob->len == ent->pub_blob->len &&
!memcmp(this_blob->s, ent->pub_blob->s,
this_blob->len))
toret = true;
strbuf_free(this_blob);
}
return toret;
}
bool ssh_transient_hostkey_cache_has(
ssh_transient_hostkey_cache *thc, const ssh_keyalg *alg)
{
struct ssh_transient_hostkey_cache_entry *ent =
find234(thc->cache, (void *)alg,
ssh_transient_hostkey_cache_find);
return ent != NULL;
}
bool ssh_transient_hostkey_cache_non_empty(ssh_transient_hostkey_cache *thc)
{
return count234(thc->cache) > 0;
}