endif()
if (NETTLE_FOUND)
- target_sources(rfb PRIVATE CSecurityDH.cxx
+ target_sources(rfb PRIVATE CSecurityDH.cxx CSecurityMSLogonII.cxx
CSecurityRSAAES.cxx SSecurityRSAAES.cxx)
include_directories(${NETTLE_INCLUDE_DIRS} ${GMP_INCLUDE_DIRS})
target_link_libraries(rfb ${HOGWEED_LIBRARIES}
--- /dev/null
+/* \r
+ * Copyright (C) 2022 Dinglan Peng\r
+ * \r
+ * This is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This software is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this software; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,\r
+ * USA.\r
+ */\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include <config.h>\r
+#endif\r
+\r
+#ifndef HAVE_NETTLE\r
+#error "This header should not be compiled without HAVE_NETTLE defined"\r
+#endif\r
+\r
+#include <stdlib.h>\r
+#ifndef WIN32\r
+#include <unistd.h>\r
+#endif\r
+#include <assert.h>\r
+\r
+#include <nettle/des.h>\r
+#include <nettle/cbc.h>\r
+#include <nettle/bignum.h>\r
+#include <rfb/CSecurityMSLogonII.h>\r
+#include <rfb/CConnection.h>\r
+#include <rdr/InStream.h>\r
+#include <rdr/OutStream.h>\r
+#include <rdr/RandomStream.h>\r
+#include <rfb/Exception.h>\r
+#include <os/os.h>\r
+\r
+using namespace rfb;\r
+\r
+CSecurityMSLogonII::CSecurityMSLogonII(CConnection* cc)\r
+ : CSecurity(cc)\r
+{\r
+ mpz_init(g);\r
+ mpz_init(p);\r
+ mpz_init(A);\r
+ mpz_init(b);\r
+ mpz_init(B);\r
+ mpz_init(k);\r
+}\r
+\r
+CSecurityMSLogonII::~CSecurityMSLogonII()\r
+{\r
+ mpz_clear(g);\r
+ mpz_clear(p);\r
+ mpz_clear(A);\r
+ mpz_clear(b);\r
+ mpz_clear(B);\r
+ mpz_clear(k);\r
+}\r
+\r
+bool CSecurityMSLogonII::processMsg()\r
+{\r
+ if (readKey()) {\r
+ writeCredentials();\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+bool CSecurityMSLogonII::readKey()\r
+{\r
+ rdr::InStream* is = cc->getInStream();\r
+ if (!is->hasData(24))\r
+ return false;\r
+ rdr::U8 gBytes[8];\r
+ rdr::U8 pBytes[8];\r
+ rdr::U8 ABytes[8];\r
+ is->readBytes(gBytes, 8);\r
+ is->readBytes(pBytes, 8);\r
+ is->readBytes(ABytes, 8);\r
+ nettle_mpz_set_str_256_u(g, 8, gBytes);\r
+ nettle_mpz_set_str_256_u(p, 8, pBytes);\r
+ nettle_mpz_set_str_256_u(A, 8, ABytes);\r
+ return true;\r
+}\r
+\r
+void CSecurityMSLogonII::writeCredentials()\r
+{\r
+ CharArray username;\r
+ CharArray password;\r
+ rdr::RandomStream rs;\r
+\r
+ (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf);\r
+ rdr::U8Array bBytes(8);\r
+ if (!rs.hasData(8))\r
+ throw ConnFailedException("failed to generate DH private key");\r
+ rs.readBytes(bBytes.buf, 8);\r
+ nettle_mpz_set_str_256_u(b, 8, bBytes.buf);\r
+ mpz_powm(k, A, b, p);\r
+ mpz_powm(B, g, b, p);\r
+\r
+ rdr::U8 key[8];\r
+ rdr::U8 reversedKey[8];\r
+ rdr::U8 BBytes[8];\r
+ rdr::U8 user[256];\r
+ rdr::U8 pass[64];\r
+ nettle_mpz_get_str_256(8, key, k);\r
+ nettle_mpz_get_str_256(8, BBytes, B);\r
+ for (int i = 0; i < 8; ++i) {\r
+ rdr::U8 x = 0;\r
+ for (int j = 0; j < 8; ++j) {\r
+ x |= ((key[i] >> j) & 1) << (7 - j);\r
+ }\r
+ reversedKey[i] = x;\r
+ }\r
+\r
+ if (!rs.hasData(256 + 64))\r
+ throw ConnFailedException("failed to generate random padding");\r
+ rs.readBytes(user, 256);\r
+ rs.readBytes(pass, 64);\r
+ size_t len = strlen(username.buf);\r
+ if (len >= 256)\r
+ throw AuthFailureException("username is too long");\r
+ memcpy(user, username.buf, len + 1);\r
+ len = strlen(password.buf);\r
+ if (len >= 64)\r
+ throw AuthFailureException("password is too long");\r
+ memcpy(pass, password.buf, len + 1);\r
+\r
+ // DES-CBC with the original key as IV, and the reversed one as the DES key\r
+ struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx;\r
+ des_fix_parity(8, reversedKey, reversedKey);\r
+ des_set_key(&ctx.ctx, reversedKey);\r
+ CBC_SET_IV(&ctx, key);\r
+ CBC_ENCRYPT(&ctx, des_encrypt, 256, user, user);\r
+ CBC_SET_IV(&ctx, key);\r
+ CBC_ENCRYPT(&ctx, des_encrypt, 64, pass, pass);\r
+\r
+ rdr::OutStream* os = cc->getOutStream();\r
+ os->writeBytes(BBytes, 8);\r
+ os->writeBytes(user, 256);\r
+ os->writeBytes(pass, 64);\r
+ os->flush();\r
+}\r
--- /dev/null
+/* \r
+ * Copyright (C) 2022 Dinglan Peng\r
+ * \r
+ * This is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This software is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this software; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,\r
+ * USA.\r
+ */\r
+\r
+#ifndef __C_SECURITY_MSLOGONII_H__\r
+#define __C_SECURITY_MSLOGONII_H__\r
+\r
+#ifndef HAVE_NETTLE\r
+#error "This header should not be compiled without HAVE_NETTLE defined"\r
+#endif\r
+\r
+#include <nettle/bignum.h>\r
+#include <rfb/CSecurity.h>\r
+#include <rfb/Security.h>\r
+\r
+namespace rfb {\r
+ class CSecurityMSLogonII : public CSecurity {\r
+ public:\r
+ CSecurityMSLogonII(CConnection* cc);\r
+ virtual ~CSecurityMSLogonII();\r
+ virtual bool processMsg();\r
+ virtual int getType() const { return secTypeMSLogonII; }\r
+ virtual bool isSecure() const { return false; }\r
+\r
+ private:\r
+ bool readKey();\r
+ void writeCredentials();\r
+\r
+ mpz_t g, p, A, b, B, k;\r
+ };\r
+}\r
+\r
+#endif\r
if (strcasecmp(name, "SSPIne") == 0) return secTypeSSPIne;
if (strcasecmp(name, "VeNCrypt") == 0) return secTypeVeNCrypt;
if (strcasecmp(name, "DH") == 0) return secTypeDH;
+ if (strcasecmp(name, "MSLogonII") == 0) return secTypeMSLogonII;
/* VeNCrypt subtypes */
if (strcasecmp(name, "Plain") == 0) return secTypePlain;
case secTypeSSPIne: return "SSPIne";
case secTypeVeNCrypt: return "VeNCrypt";
case secTypeDH: return "DH";
+ case secTypeMSLogonII: return "MSLogonII";
/* VeNCrypt subtypes */
case secTypePlain: return "Plain";
#include <list>
namespace rfb {
- const rdr::U8 secTypeInvalid = 0;
- const rdr::U8 secTypeNone = 1;
- const rdr::U8 secTypeVncAuth = 2;
+ const rdr::U8 secTypeInvalid = 0;
+ const rdr::U8 secTypeNone = 1;
+ const rdr::U8 secTypeVncAuth = 2;
- const rdr::U8 secTypeRA2 = 5;
- const rdr::U8 secTypeRA2ne = 6;
+ const rdr::U8 secTypeRA2 = 5;
+ const rdr::U8 secTypeRA2ne = 6;
- const rdr::U8 secTypeSSPI = 7;
- const rdr::U8 secTypeSSPIne = 8;
+ const rdr::U8 secTypeSSPI = 7;
+ const rdr::U8 secTypeSSPIne = 8;
- const rdr::U8 secTypeTight = 16;
- const rdr::U8 secTypeUltra = 17;
- const rdr::U8 secTypeTLS = 18;
- const rdr::U8 secTypeVeNCrypt= 19;
+ const rdr::U8 secTypeTight = 16;
+ const rdr::U8 secTypeUltra = 17;
+ const rdr::U8 secTypeTLS = 18;
+ const rdr::U8 secTypeVeNCrypt = 19;
- const rdr::U8 secTypeDH = 30;
+ const rdr::U8 secTypeDH = 30;
- const rdr::U8 secTypeRA256 = 129;
- const rdr::U8 secTypeRAne256 = 130;
+ const rdr::U8 secTypeMSLogonII = 113;
+
+ const rdr::U8 secTypeRA256 = 129;
+ const rdr::U8 secTypeRAne256 = 130;
/* VeNCrypt subtypes */
- const int secTypePlain = 256;
- const int secTypeTLSNone = 257;
- const int secTypeTLSVnc = 258;
- const int secTypeTLSPlain = 259;
- const int secTypeX509None = 260;
- const int secTypeX509Vnc = 261;
- const int secTypeX509Plain = 262;
+ const int secTypePlain = 256;
+ const int secTypeTLSNone = 257;
+ const int secTypeTLSVnc = 258;
+ const int secTypeTLSPlain = 259;
+ const int secTypeX509None = 260;
+ const int secTypeX509Vnc = 261;
+ const int secTypeX509Plain = 262;
/* RSA-AES subtypes */
- const int secTypeRA2UserPass = 1;
- const int secTypeRA2Pass = 2;
+ const int secTypeRA2UserPass = 1;
+ const int secTypeRA2Pass = 2;
// result types
#ifdef HAVE_NETTLE
#include <rfb/CSecurityRSAAES.h>
#include <rfb/CSecurityDH.h>
+#include <rfb/CSecurityMSLogonII.h>
#endif
using namespace rdr;
", TLSNone, TLSVnc, TLSPlain, X509None, X509Vnc, X509Plain"
#endif
#ifdef HAVE_NETTLE
- ", RA2, RA2ne, RA2_256, RA2ne_256, DH"
+ ", RA2, RA2ne, RA2_256, RA2ne_256, DH, MSLogonII"
#endif
")",
#ifdef HAVE_GNUTLS
"X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,"
#endif
#ifdef HAVE_NETTLE
- "RA2,RA2_256,RA2ne,RA2ne_256,DH"
+ "RA2,RA2_256,RA2ne,RA2ne_256,DH,MSLogonII"
#endif
"VncAuth,None",
ConfViewer);
return new CSecurityRSAAES(cc, secTypeRAne256, 256, false);
case secTypeDH:
return new CSecurityDH(cc);
+ case secTypeMSLogonII:
+ return new CSecurityMSLogonII(cc);
#endif
}
case secTypeRAne256:
authVncCheckbox->value(true);
case secTypeDH:
+ case secTypeMSLogonII:
encNoneCheckbox->value(true);
authPlainCheckbox->value(true);
break;
security.EnableSecType(secTypeRA2ne);
security.EnableSecType(secTypeRAne256);
security.EnableSecType(secTypeDH);
+ security.EnableSecType(secTypeMSLogonII);
#endif
}
}