Bläddra i källkod

Add client-side support for the MSLogonII security type.

pull/1566/head
Dinglan Peng 1 år sedan
förälder
incheckning
40e24436e3

+ 1
- 1
common/rfb/CMakeLists.txt Visa fil

@@ -103,7 +103,7 @@ if(GNUTLS_FOUND)
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}

+ 151
- 0
common/rfb/CSecurityMSLogonII.cxx Visa fil

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2022 Dinglan Peng
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef HAVE_NETTLE
#error "This header should not be compiled without HAVE_NETTLE defined"
#endif
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <assert.h>
#include <nettle/des.h>
#include <nettle/cbc.h>
#include <nettle/bignum.h>
#include <rfb/CSecurityMSLogonII.h>
#include <rfb/CConnection.h>
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
#include <rdr/RandomStream.h>
#include <rfb/Exception.h>
#include <os/os.h>
using namespace rfb;
CSecurityMSLogonII::CSecurityMSLogonII(CConnection* cc)
: CSecurity(cc)
{
mpz_init(g);
mpz_init(p);
mpz_init(A);
mpz_init(b);
mpz_init(B);
mpz_init(k);
}
CSecurityMSLogonII::~CSecurityMSLogonII()
{
mpz_clear(g);
mpz_clear(p);
mpz_clear(A);
mpz_clear(b);
mpz_clear(B);
mpz_clear(k);
}
bool CSecurityMSLogonII::processMsg()
{
if (readKey()) {
writeCredentials();
return true;
}
return false;
}
bool CSecurityMSLogonII::readKey()
{
rdr::InStream* is = cc->getInStream();
if (!is->hasData(24))
return false;
rdr::U8 gBytes[8];
rdr::U8 pBytes[8];
rdr::U8 ABytes[8];
is->readBytes(gBytes, 8);
is->readBytes(pBytes, 8);
is->readBytes(ABytes, 8);
nettle_mpz_set_str_256_u(g, 8, gBytes);
nettle_mpz_set_str_256_u(p, 8, pBytes);
nettle_mpz_set_str_256_u(A, 8, ABytes);
return true;
}
void CSecurityMSLogonII::writeCredentials()
{
CharArray username;
CharArray password;
rdr::RandomStream rs;
(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf);
rdr::U8Array bBytes(8);
if (!rs.hasData(8))
throw ConnFailedException("failed to generate DH private key");
rs.readBytes(bBytes.buf, 8);
nettle_mpz_set_str_256_u(b, 8, bBytes.buf);
mpz_powm(k, A, b, p);
mpz_powm(B, g, b, p);
rdr::U8 key[8];
rdr::U8 reversedKey[8];
rdr::U8 BBytes[8];
rdr::U8 user[256];
rdr::U8 pass[64];
nettle_mpz_get_str_256(8, key, k);
nettle_mpz_get_str_256(8, BBytes, B);
for (int i = 0; i < 8; ++i) {
rdr::U8 x = 0;
for (int j = 0; j < 8; ++j) {
x |= ((key[i] >> j) & 1) << (7 - j);
}
reversedKey[i] = x;
}
if (!rs.hasData(256 + 64))
throw ConnFailedException("failed to generate random padding");
rs.readBytes(user, 256);
rs.readBytes(pass, 64);
size_t len = strlen(username.buf);
if (len >= 256)
throw AuthFailureException("username is too long");
memcpy(user, username.buf, len + 1);
len = strlen(password.buf);
if (len >= 64)
throw AuthFailureException("password is too long");
memcpy(pass, password.buf, len + 1);
// DES-CBC with the original key as IV, and the reversed one as the DES key
struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx;
des_fix_parity(8, reversedKey, reversedKey);
des_set_key(&ctx.ctx, reversedKey);
CBC_SET_IV(&ctx, key);
CBC_ENCRYPT(&ctx, des_encrypt, 256, user, user);
CBC_SET_IV(&ctx, key);
CBC_ENCRYPT(&ctx, des_encrypt, 64, pass, pass);
rdr::OutStream* os = cc->getOutStream();
os->writeBytes(BBytes, 8);
os->writeBytes(user, 256);
os->writeBytes(pass, 64);
os->flush();
}

+ 48
- 0
common/rfb/CSecurityMSLogonII.h Visa fil

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2022 Dinglan Peng
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef __C_SECURITY_MSLOGONII_H__
#define __C_SECURITY_MSLOGONII_H__
#ifndef HAVE_NETTLE
#error "This header should not be compiled without HAVE_NETTLE defined"
#endif
#include <nettle/bignum.h>
#include <rfb/CSecurity.h>
#include <rfb/Security.h>
namespace rfb {
class CSecurityMSLogonII : public CSecurity {
public:
CSecurityMSLogonII(CConnection* cc);
virtual ~CSecurityMSLogonII();
virtual bool processMsg();
virtual int getType() const { return secTypeMSLogonII; }
virtual bool isSecure() const { return false; }
private:
bool readKey();
void writeCredentials();
mpz_t g, p, A, b, B, k;
};
}
#endif

+ 2
- 0
common/rfb/Security.cxx Visa fil

@@ -166,6 +166,7 @@ rdr::U32 rfb::secTypeNum(const char* name)
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;
@@ -193,6 +194,7 @@ const char* rfb::secTypeName(rdr::U32 num)
case secTypeSSPIne: return "SSPIne";
case secTypeVeNCrypt: return "VeNCrypt";
case secTypeDH: return "DH";
case secTypeMSLogonII: return "MSLogonII";

/* VeNCrypt subtypes */
case secTypePlain: return "Plain";

+ 25
- 23
common/rfb/Security.h Visa fil

@@ -28,38 +28,40 @@
#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


+ 5
- 2
common/rfb/SecurityClient.cxx Visa fil

@@ -35,6 +35,7 @@
#ifdef HAVE_NETTLE
#include <rfb/CSecurityRSAAES.h>
#include <rfb/CSecurityDH.h>
#include <rfb/CSecurityMSLogonII.h>
#endif

using namespace rdr;
@@ -52,14 +53,14 @@ StringParameter SecurityClient::secTypes
", 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);
@@ -114,6 +115,8 @@ CSecurity* SecurityClient::GetCSecurity(CConnection* cc, U32 secType)
return new CSecurityRSAAES(cc, secTypeRAne256, 256, false);
case secTypeDH:
return new CSecurityDH(cc);
case secTypeMSLogonII:
return new CSecurityMSLogonII(cc);
#endif
}


+ 2
- 0
vncviewer/OptionsDialog.cxx Visa fil

@@ -296,6 +296,7 @@ void OptionsDialog::loadOptions(void)
case secTypeRAne256:
authVncCheckbox->value(true);
case secTypeDH:
case secTypeMSLogonII:
encNoneCheckbox->value(true);
authPlainCheckbox->value(true);
break;
@@ -410,6 +411,7 @@ void OptionsDialog::storeOptions(void)
security.EnableSecType(secTypeRA2ne);
security.EnableSecType(secTypeRAne256);
security.EnableSecType(secTypeDH);
security.EnableSecType(secTypeMSLogonII);
#endif
}
}

Laddar…
Avbryt
Spara