Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,11 @@ if(SYSTEMD_FOUND)
endif(SYSTEMD_FOUND)

# common crypto used by both libvncserver and libvncclient
if(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES)
if(APPLE AND OPENSSL_FOUND)
message(STATUS "Building crypto with OpenSSL")
set(CRYPTO_LIBRARIES ${OPENSSL_LIBRARIES})
set(CRYPTO_SOURCES ${COMMON_DIR}/crypto_openssl.c)
elseif(WITH_GCRYPT AND LIBGCRYPT_LIBRARIES)
message(STATUS "Building crypto with Libgcrypt")
set(CRYPTO_LIBRARIES ${LIBGCRYPT_LIBRARIES})
set(CRYPTO_SOURCES ${COMMON_DIR}/crypto_libgcrypt.c)
Expand Down Expand Up @@ -378,6 +382,7 @@ set(LIBVNCSERVER_SOURCES
set(LIBVNCCLIENT_SOURCES
${LIBVNCCLIENT_DIR}/cursor.c
${LIBVNCCLIENT_DIR}/listen.c
${LIBVNCCLIENT_DIR}/ardauth.c
${LIBVNCCLIENT_DIR}/rfbclient.c
${LIBVNCCLIENT_DIR}/sockets.c
${LIBVNCCLIENT_DIR}/vncviewer.c
Expand Down Expand Up @@ -516,6 +521,9 @@ if(WITH_LIBVNCCLIENT)
${GNUTLS_LIBRARIES}
${OPENSSL_LIBRARIES}
)
if(APPLE)
target_link_libraries(vncclient "-framework CoreFoundation" "-framework GSS" "-framework Kerberos")
endif()
set(LIBVNCSERVER_LIBRARIES vncclient)
endif(WITH_LIBVNCCLIENT)
if(WITH_LIBVNCSERVER)
Expand Down Expand Up @@ -596,6 +604,7 @@ endif(X11_xcb_FOUND AND X11_xcb_xtest_FOUND AND X11_xcb_keysyms_FOUND)

set(LIBVNCCLIENT_EXAMPLES
backchannel
ardauthprobe
ppmtest
)

Expand Down Expand Up @@ -644,7 +653,11 @@ if(WITH_EXAMPLES)

if(WITH_LIBVNCCLIENT)
foreach(e ${LIBVNCCLIENT_EXAMPLES})
add_executable(client_examples_${e} ${LIBVNCCLIEXAMPLE_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
if(EXISTS ${TESTS_DIR}/${e}.c)
add_executable(client_examples_${e} ${TESTS_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
else()
add_executable(client_examples_${e} ${LIBVNCCLIEXAMPLE_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
endif()
set_target_properties(client_examples_${e} PROPERTIES OUTPUT_NAME ${e})
set_target_properties(client_examples_${e} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL2_LIBRARY} ${GTK2_LIBRARIES} ${FFMPEG_LIBRARIES} ${LIBSSHTUNNEL_LIBRARY})
Expand Down
8 changes: 8 additions & 0 deletions include/rfb/rfbclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ typedef struct _rfbClient {
* Set by function SetClientAuthSchemes() */
uint32_t *clientAuthSchemes;

/** Optional configuration for ARD Kerberos auth. */
char *ardAuthRealm;
char *ardAuthClientPrincipal;
char *ardAuthServicePrincipal;

/** When the server is a repeater, this specifies the final destination */
char *destHost;
int destPort;
Expand Down Expand Up @@ -529,6 +534,9 @@ extern rfbClientLogProc rfbClientLog,rfbClientErr;
extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port);
extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort);
extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size);
extern rfbBool rfbClientSetARDAuthRealm(rfbClient *client, const char *realm);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please doc-comment these

extern rfbBool rfbClientSetARDAuthClientPrincipal(rfbClient *client, const char *principal);
extern rfbBool rfbClientSetARDAuthServicePrincipal(rfbClient *client, const char *principal);
extern rfbBool InitialiseRFBConnection(rfbClient* client);
/**
* Sends format and encoding parameters to the server. Your application can
Expand Down
5 changes: 4 additions & 1 deletion include/rfb/rfbproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
#define rfbTLS 18
#define rfbVeNCrypt 19
#define rfbSASL 20
#define rfbARD 30
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't change the API here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have thought about this. The issue is that ARD is the name for the full protocol, but authType 30 is just one of several authentication methods. Since this PR aims to add support for more authentication types, I think maybe this adjustment is worth considering.

#define rfbARDAuthDH 30
#define rfbARDAuthRSASRP 33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add comments here what these are

#define rfbARDAuthKerberosGSSAPI 35
#define rfbARDAuthDirectSRP 36
#define rfbUltraMSLogonI 0x70 /* UNIMPLEMENTED */
#define rfbUltraMSLogonII 0x71
#define rfbMSLogon 0xfffffffa
Expand Down
13 changes: 13 additions & 0 deletions src/common/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "rfb/rfbconfig.h"

#define SHA1_HASH_SIZE 20
#define SHA512_HASH_SIZE 64
#define MD5_HASH_SIZE 16

/* Generates an MD5 hash of 'in' and writes it to 'out', which must be 16 bytes in size. */
Expand All @@ -13,6 +14,9 @@ int hash_md5(void *out, const void *in, const size_t in_len);
/* Generates an SHA1 hash of 'in' and writes it to 'out', which must be 20 bytes in size. */
int hash_sha1(void *out, const void *in, const size_t in_len);

/* Generates an SHA512 hash of 'in' and writes it to 'out', which must be 64 bytes in size. */
int hash_sha512(void *out, const void *in, const size_t in_len);

/* Fill 'out' with 'len' random bytes. */
void random_bytes(void *out, size_t len);

Expand All @@ -31,6 +35,15 @@ int decrypt_rfbdes(void *out, int *out_len, const unsigned char key[8], const vo
/* Encrypts 'in' with the the 16-byte key in 'key' using AES-128-ECB and writes the result to 'out'. */
int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], const void *in, const size_t in_len);

/* Derives key material with PBKDF2-HMAC-SHA512. */
int pbkdf2_hmac_sha512(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint32_t rounds, uint8_t *out, size_t out_len);

/*
Imports an RSA public key from SubjectPublicKeyInfo DER and encrypts 'in'
with PKCS#1 v1.5 padding, writing the ciphertext to 'out'.
*/
int encrypt_rsa_pkcs1_spki_der(uint8_t *out, size_t *out_len, const uint8_t *der, size_t der_len, const void *in, size_t in_len);

/*
Generates a Diffie-Hellman public-private keypair using the generator value 'gen' and prime modulo
'prime', writing the result to 'pub_out' and 'priv_out', which must be 'keylen' in size.
Expand Down
31 changes: 31 additions & 0 deletions src/common/crypto_included.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ int hash_sha1(void *out, const void *in, const size_t in_len)
return 1;
}

int hash_sha512(void *out, const void *in, const size_t in_len)
{
(void)out;
(void)in;
(void)in_len;
return 0;
}

void random_bytes(void *out, size_t len)
{

Expand Down Expand Up @@ -82,6 +90,29 @@ int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], cons
return 0;
}

int pbkdf2_hmac_sha512(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint32_t rounds, uint8_t *out, size_t out_len)
{
(void)password;
(void)password_len;
(void)salt;
(void)salt_len;
(void)rounds;
(void)out;
(void)out_len;
return 0;
}

int encrypt_rsa_pkcs1_spki_der(uint8_t *out, size_t *out_len, const uint8_t *der, size_t der_len, const void *in, size_t in_len)
{
(void)out;
(void)out_len;
(void)der;
(void)der_len;
(void)in;
(void)in_len;
return 0;
}

int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen)
{
return 0;
Expand Down
52 changes: 52 additions & 0 deletions src/common/crypto_libgcrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,31 @@ int hash_sha1(void *out, const void *in, const size_t in_len)
return result;
}

int hash_sha512(void *out, const void *in, const size_t in_len)
{
int result = 0;
gcry_error_t error;
gcry_md_hd_t sha512 = NULL;
void *digest;

error = gcry_md_open(&sha512, GCRY_MD_SHA512, 0);
if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
goto out;

gcry_md_write(sha512, in, in_len);

if(!(digest = gcry_md_read(sha512, GCRY_MD_SHA512)))
goto out;

memcpy(out, digest, gcry_md_get_algo_dlen(GCRY_MD_SHA512));

result = 1;

out:
gcry_md_close(sha512);
return result;
}

void random_bytes(void *out, size_t len)
{
gcry_randomize(out, len, GCRY_STRONG_RANDOM);
Expand Down Expand Up @@ -195,6 +220,33 @@ int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], cons
return result;
}

int pbkdf2_hmac_sha512(const uint8_t *password, size_t password_len,
const uint8_t *salt, size_t salt_len, uint32_t rounds,
uint8_t *out, size_t out_len)
{
gcry_error_t error;

if (!password || !salt || !out || out_len == 0)
return 0;

error = gcry_kdf_derive(password, password_len, GCRY_KDF_PBKDF2, GCRY_MD_SHA512,
salt, salt_len, rounds ? rounds : 1, out_len, out);
return gcry_err_code(error) == GPG_ERR_NO_ERROR;
}

int encrypt_rsa_pkcs1_spki_der(uint8_t *out, size_t *out_len,
const uint8_t *der, size_t der_len,
const void *in, size_t in_len)
{
(void)out;
(void)out_len;
(void)der;
(void)der_len;
(void)in;
(void)in_len;
return 0;
}

int dh_generate_keypair(uint8_t *priv_out, uint8_t *pub_out, const uint8_t *gen, const size_t gen_len, const uint8_t *prime, const size_t keylen)
{
int result = 0;
Expand Down
75 changes: 75 additions & 0 deletions src/common/crypto_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <openssl/dh.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#include <openssl/provider.h>
#endif
Expand Down Expand Up @@ -64,6 +66,28 @@ int hash_sha1(void *out, const void *in, const size_t in_len)
return 1;
}

int hash_sha512(void *out, const void *in, const size_t in_len)
{
EVP_MD_CTX *ctx = NULL;
int result = 0;
unsigned int digest_len = 0;

if (!(ctx = EVP_MD_CTX_new()))
goto out;
if (!EVP_DigestInit_ex(ctx, EVP_sha512(), NULL))
goto out;
if (!EVP_DigestUpdate(ctx, in, in_len))
goto out;
if (!EVP_DigestFinal_ex(ctx, out, &digest_len))
goto out;

result = digest_len == SHA512_HASH_SIZE;

out:
EVP_MD_CTX_free(ctx);
return result;
}

void random_bytes(void *out, size_t len)
{
RAND_bytes(out, len);
Expand Down Expand Up @@ -177,6 +201,57 @@ int encrypt_aes128ecb(void *out, int *out_len, const unsigned char key[16], cons
return result;
}

int pbkdf2_hmac_sha512(const uint8_t *password, size_t password_len,
const uint8_t *salt, size_t salt_len, uint32_t rounds,
uint8_t *out, size_t out_len)
{
if (!password || !salt || !out || out_len == 0)
return 0;
return PKCS5_PBKDF2_HMAC((const char *)password, (int)password_len, salt,
(int)salt_len, rounds ? (int)rounds : 1,
EVP_sha512(), (int)out_len, out) == 1;
}

int encrypt_rsa_pkcs1_spki_der(uint8_t *out, size_t *out_len,
const uint8_t *der, size_t der_len,
const void *in, size_t in_len)
{
int result = 0;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
const unsigned char *derp = der;
size_t required_len = 0;

if (!out || !out_len || !der || !in)
goto out;

pkey = d2i_PUBKEY(NULL, &derp, (long)der_len);
if (!pkey || EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
goto out;

ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx)
goto out;
if (EVP_PKEY_encrypt_init(ctx) <= 0)
goto out;
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
goto out;
if (EVP_PKEY_encrypt(ctx, NULL, &required_len, in, in_len) <= 0)
goto out;
if (required_len > *out_len)
goto out;
if (EVP_PKEY_encrypt(ctx, out, &required_len, in, in_len) <= 0)
goto out;

*out_len = required_len;
result = 1;

out:
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return result;
}

static void pad_leading_zeros(uint8_t *out, const size_t current_len, const size_t expected_len) {
if (current_len >= expected_len || expected_len < 1)
return;
Expand Down
Loading
Loading