transient-hostkey-cache.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Data structure managing host keys in sessions based on GSSAPI KEX.
  3. *
  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.
  11. *
  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.
  16. *
  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.
  22. */
  23. #include <assert.h>
  24. #include "putty.h"
  25. #include "ssh.h"
  26. struct ssh_transient_hostkey_cache {
  27. tree234 *cache;
  28. };
  29. struct ssh_transient_hostkey_cache_entry {
  30. const ssh_keyalg *alg;
  31. strbuf *pub_blob;
  32. };
  33. static int ssh_transient_hostkey_cache_cmp(void *av, void *bv)
  34. {
  35. const struct ssh_transient_hostkey_cache_entry
  36. *a = (const struct ssh_transient_hostkey_cache_entry *)av,
  37. *b = (const struct ssh_transient_hostkey_cache_entry *)bv;
  38. return strcmp(a->alg->ssh_id, b->alg->ssh_id);
  39. }
  40. static int ssh_transient_hostkey_cache_find(void *av, void *bv)
  41. {
  42. const ssh_keyalg *aalg = (const ssh_keyalg *)av;
  43. const struct ssh_transient_hostkey_cache_entry
  44. *b = (const struct ssh_transient_hostkey_cache_entry *)bv;
  45. return strcmp(aalg->ssh_id, b->alg->ssh_id);
  46. }
  47. ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void)
  48. {
  49. ssh_transient_hostkey_cache *thc = snew(ssh_transient_hostkey_cache);
  50. thc->cache = newtree234(ssh_transient_hostkey_cache_cmp);
  51. return thc;
  52. }
  53. void ssh_transient_hostkey_cache_free(ssh_transient_hostkey_cache *thc)
  54. {
  55. struct ssh_transient_hostkey_cache_entry *ent;
  56. while ((ent = delpos234(thc->cache, 0)) != NULL) {
  57. strbuf_free(ent->pub_blob);
  58. sfree(ent);
  59. }
  60. freetree234(thc->cache);
  61. sfree(thc);
  62. }
  63. void ssh_transient_hostkey_cache_add(
  64. ssh_transient_hostkey_cache *thc, ssh_key *key)
  65. {
  66. struct ssh_transient_hostkey_cache_entry *ent, *retd;
  67. if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
  68. ssh_transient_hostkey_cache_find)) != NULL) {
  69. del234(thc->cache, ent);
  70. strbuf_free(ent->pub_blob);
  71. sfree(ent);
  72. }
  73. ent = snew(struct ssh_transient_hostkey_cache_entry);
  74. ent->alg = ssh_key_alg(key);
  75. ent->pub_blob = strbuf_new();
  76. ssh_key_public_blob(key, BinarySink_UPCAST(ent->pub_blob));
  77. retd = add234(thc->cache, ent);
  78. assert(retd == ent);
  79. }
  80. bool ssh_transient_hostkey_cache_verify(
  81. ssh_transient_hostkey_cache *thc, ssh_key *key)
  82. {
  83. struct ssh_transient_hostkey_cache_entry *ent;
  84. bool toret = false;
  85. if ((ent = find234(thc->cache, (void *)ssh_key_alg(key),
  86. ssh_transient_hostkey_cache_find)) != NULL) {
  87. strbuf *this_blob = strbuf_new();
  88. ssh_key_public_blob(key, BinarySink_UPCAST(this_blob));
  89. if (this_blob->len == ent->pub_blob->len &&
  90. !memcmp(this_blob->s, ent->pub_blob->s,
  91. this_blob->len))
  92. toret = true;
  93. strbuf_free(this_blob);
  94. }
  95. return toret;
  96. }
  97. bool ssh_transient_hostkey_cache_has(
  98. ssh_transient_hostkey_cache *thc, const ssh_keyalg *alg)
  99. {
  100. struct ssh_transient_hostkey_cache_entry *ent =
  101. find234(thc->cache, (void *)alg,
  102. ssh_transient_hostkey_cache_find);
  103. return ent != NULL;
  104. }
  105. bool ssh_transient_hostkey_cache_non_empty(ssh_transient_hostkey_cache *thc)
  106. {
  107. return count234(thc->cache) > 0;
  108. }