Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

CSecurityMSLogonII.cxx 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (C) 2022 Dinglan Peng
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #ifndef HAVE_NETTLE
  23. #error "This header should not be compiled without HAVE_NETTLE defined"
  24. #endif
  25. #include <stdlib.h>
  26. #ifndef WIN32
  27. #include <unistd.h>
  28. #endif
  29. #include <assert.h>
  30. #include <nettle/des.h>
  31. #include <nettle/cbc.h>
  32. #include <nettle/bignum.h>
  33. #include <rfb/CSecurityMSLogonII.h>
  34. #include <rfb/CConnection.h>
  35. #include <rdr/InStream.h>
  36. #include <rdr/OutStream.h>
  37. #include <rdr/RandomStream.h>
  38. #include <rdr/types.h>
  39. #include <rfb/Exception.h>
  40. #include <os/os.h>
  41. using namespace rfb;
  42. CSecurityMSLogonII::CSecurityMSLogonII(CConnection* cc)
  43. : CSecurity(cc)
  44. {
  45. mpz_init(g);
  46. mpz_init(p);
  47. mpz_init(A);
  48. mpz_init(b);
  49. mpz_init(B);
  50. mpz_init(k);
  51. }
  52. CSecurityMSLogonII::~CSecurityMSLogonII()
  53. {
  54. mpz_clear(g);
  55. mpz_clear(p);
  56. mpz_clear(A);
  57. mpz_clear(b);
  58. mpz_clear(B);
  59. mpz_clear(k);
  60. }
  61. bool CSecurityMSLogonII::processMsg()
  62. {
  63. if (readKey()) {
  64. writeCredentials();
  65. return true;
  66. }
  67. return false;
  68. }
  69. bool CSecurityMSLogonII::readKey()
  70. {
  71. rdr::InStream* is = cc->getInStream();
  72. if (!is->hasData(24))
  73. return false;
  74. uint8_t gBytes[8];
  75. uint8_t pBytes[8];
  76. uint8_t ABytes[8];
  77. is->readBytes(gBytes, 8);
  78. is->readBytes(pBytes, 8);
  79. is->readBytes(ABytes, 8);
  80. nettle_mpz_set_str_256_u(g, 8, gBytes);
  81. nettle_mpz_set_str_256_u(p, 8, pBytes);
  82. nettle_mpz_set_str_256_u(A, 8, ABytes);
  83. return true;
  84. }
  85. void CSecurityMSLogonII::writeCredentials()
  86. {
  87. CharArray username;
  88. CharArray password;
  89. rdr::RandomStream rs;
  90. (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf);
  91. rdr::U8Array bBytes(8);
  92. if (!rs.hasData(8))
  93. throw ConnFailedException("failed to generate DH private key");
  94. rs.readBytes(bBytes.buf, 8);
  95. nettle_mpz_set_str_256_u(b, 8, bBytes.buf);
  96. mpz_powm(k, A, b, p);
  97. mpz_powm(B, g, b, p);
  98. uint8_t key[8];
  99. uint8_t reversedKey[8];
  100. uint8_t BBytes[8];
  101. uint8_t user[256];
  102. uint8_t pass[64];
  103. nettle_mpz_get_str_256(8, key, k);
  104. nettle_mpz_get_str_256(8, BBytes, B);
  105. for (int i = 0; i < 8; ++i) {
  106. uint8_t x = 0;
  107. for (int j = 0; j < 8; ++j) {
  108. x |= ((key[i] >> j) & 1) << (7 - j);
  109. }
  110. reversedKey[i] = x;
  111. }
  112. if (!rs.hasData(256 + 64))
  113. throw ConnFailedException("failed to generate random padding");
  114. rs.readBytes(user, 256);
  115. rs.readBytes(pass, 64);
  116. size_t len = strlen(username.buf);
  117. if (len >= 256)
  118. throw AuthFailureException("username is too long");
  119. memcpy(user, username.buf, len + 1);
  120. len = strlen(password.buf);
  121. if (len >= 64)
  122. throw AuthFailureException("password is too long");
  123. memcpy(pass, password.buf, len + 1);
  124. // DES-CBC with the original key as IV, and the reversed one as the DES key
  125. struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx;
  126. des_fix_parity(8, reversedKey, reversedKey);
  127. des_set_key(&ctx.ctx, reversedKey);
  128. CBC_SET_IV(&ctx, key);
  129. CBC_ENCRYPT(&ctx, des_encrypt, 256, user, user);
  130. CBC_SET_IV(&ctx, key);
  131. CBC_ENCRYPT(&ctx, des_encrypt, 64, pass, pass);
  132. rdr::OutStream* os = cc->getOutStream();
  133. os->writeBytes(BBytes, 8);
  134. os->writeBytes(user, 256);
  135. os->writeBytes(pass, 64);
  136. os->flush();
  137. }