Upgrade libgit2
[TortoiseGit.git] / src / TortoisePlink / ssh / transient-hostkey-cache.c
blobeba6079cd1836bcd4bcb77451c0b3d93806ce6f6
1 /*
2 * Data structure managing host keys in sessions based on GSSAPI KEX.
4 * In a session we started with a GSSAPI key exchange, the concept of
5 * 'host key' has completely different lifetime and security semantics
6 * from the usual ones. Per RFC 4462 section 2.1, we assume that any
7 * host key delivered to us in the course of a GSSAPI key exchange is
8 * _solely_ there to use as a transient fallback within the same
9 * session, if at the time of a subsequent rekey the GSS credentials
10 * are temporarily invalid and so a non-GSS KEX method has to be used.
12 * In particular, in a GSS-based SSH deployment, host keys may not
13 * even _be_ persistent identities for the server; it would be
14 * legitimate for a server to generate a fresh one routinely if it
15 * wanted to, like SSH-1 server keys.
17 * So, in this mode, we never touch the persistent host key cache at
18 * all, either to check keys against it _or_ to store keys in it.
19 * Instead, we maintain an in-memory cache of host keys that have been
20 * mentioned in GSS key exchanges within this particular session, and
21 * we permit precisely those host keys in non-GSS rekeys.
24 #include <assert.h>
26 #include "putty.h"
27 #include "ssh.h"
29 struct ssh_transient_hostkey_cache {
30 tree234 *cache;
33 struct ssh_transient_hostkey_cache_entry {
34 const ssh_keyalg *alg;
35 strbuf *pub_blob;
38 static int ssh_transient_hostkey_cache_cmp(void *av, void *bv)
40 const struct ssh_transient_hostkey_cache_entry
41 *a = (const struct ssh_transient_hostkey_cache_entry *)av,
42 *b = (const struct ssh_transient_hostkey_cache_entry *)bv;
43 return strcmp(a->alg->ssh_id, b->alg->ssh_id);
46 static int ssh_transient_hostkey_cache_find(void *av, void *bv)
48 const ssh_keyalg *aalg = (const ssh_keyalg *)av;
49 const struct ssh_transient_hostkey_cache_entry
50 *b = (const struct ssh_transient_hostkey_cache_entry *)bv;
51 return strcmp(aalg->ssh_id, b->alg->ssh_id);
54 ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void)
56 ssh_transient_hostkey_cache *thc = snew(ssh_transient_hostkey_cache);
57 thc->cache = newtree234(ssh_transient_hostkey_cache_cmp);
58 return thc;
61 void ssh_transient_hostkey_cache_free(ssh_transient_hostkey_cache *thc)
63 struct ssh_transient_hostkey_cache_entry *ent;
64 while ((ent = delpos234(thc->cache, 0)) != NULL) {
65 strbuf_free(ent->pub_blob);
66 sfree(ent);
68 freetree234(thc->cache);
69 sfree(thc);
72 void ssh_transient_hostkey_cache_add(
73 ssh_transient_hostkey_cache *thc, ssh_key *key)
75 struct ssh_transient_hostkey_cache_entry *ent, *retd;
77 if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
78 ssh_transient_hostkey_cache_find)) != NULL) {
79 del234(thc->cache, ent);
80 strbuf_free(ent->pub_blob);
81 sfree(ent);
84 ent = snew(struct ssh_transient_hostkey_cache_entry);
85 ent->alg = ssh_key_alg(key);
86 ent->pub_blob = strbuf_new();
87 ssh_key_public_blob(key, BinarySink_UPCAST(ent->pub_blob));
88 retd = add234(thc->cache, ent);
89 assert(retd == ent);
92 bool ssh_transient_hostkey_cache_verify(
93 ssh_transient_hostkey_cache *thc, ssh_key *key)
95 struct ssh_transient_hostkey_cache_entry *ent;
96 bool toret = false;
98 if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
99 ssh_transient_hostkey_cache_find)) != NULL) {
100 strbuf *this_blob = strbuf_new();
101 ssh_key_public_blob(key, BinarySink_UPCAST(this_blob));
103 if (this_blob->len == ent->pub_blob->len &&
104 !memcmp(this_blob->s, ent->pub_blob->s,
105 this_blob->len))
106 toret = true;
108 strbuf_free(this_blob);
111 return toret;
114 bool ssh_transient_hostkey_cache_has(
115 ssh_transient_hostkey_cache *thc, const ssh_keyalg *alg)
117 struct ssh_transient_hostkey_cache_entry *ent =
118 find234(thc->cache, (void *)alg,
119 ssh_transient_hostkey_cache_find);
120 return ent != NULL;
123 bool ssh_transient_hostkey_cache_non_empty(ssh_transient_hostkey_cache *thc)
125 return count234(thc->cache) > 0;