Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
libvncserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
libvncserver
Commits
f49a2927
Commit
f49a2927
authored
Nov 02, 2009
by
Johannes Schindelin
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'VeNCrypt'
parents
67223b7c
29990f00
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1008 additions
and
96 deletions
+1008
-96
configure.ac
configure.ac
+16
-0
Makefile.am
libvncclient/Makefile.am
+3
-3
rfbproto.c
libvncclient/rfbproto.c
+324
-91
sockets.c
libvncclient/sockets.c
+31
-2
tls.c
libvncclient/tls.c
+496
-0
tls.h
libvncclient/tls.h
+51
-0
vncviewer.c
libvncclient/vncviewer.c
+9
-0
vncauth.c
libvncserver/vncauth.c
+15
-0
rfbclient.h
rfb/rfbclient.h
+51
-0
rfbproto.h
rfb/rfbproto.h
+12
-0
No files found.
configure.ac
View file @
f49a2927
...
@@ -681,6 +681,22 @@ if test ! -z "$MINGW"; then
...
@@ -681,6 +681,22 @@ if test ! -z "$MINGW"; then
fi
fi
AC_SUBST(WSOCKLIB)
AC_SUBST(WSOCKLIB)
# Checks for GnuTLS
AH_TEMPLATE(WITH_CLIENT_TLS, [Enable support for gnutls in libvncclient])
AC_ARG_WITH(gnutls,
[ --without-gnutls disable support for gnutls],,)
AC_ARG_WITH(client-tls,
[ --without-client-tls disable support for gnutls in libvncclient],,)
if test "x$with_gnutls" != "xno"; then
PKG_CHECK_MODULES(GNUTLS, gnutls >= 2.8.0, , with_client_tls=no)
CFLAGS="$CFLAGS $GNUTLS_CFLAGS"
LIBS="$LIBS $GNUTLS_LIBS"
if test "x$with_client_tls" != "xno"; then
AC_DEFINE(WITH_CLIENT_TLS)
fi
fi
# Checks for header files.
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_STDC
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h])
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h])
...
...
libvncclient/Makefile.am
View file @
f49a2927
INCLUDES
=
-I
$(top_srcdir)
INCLUDES
=
-I
$(top_srcdir)
libvncclient_la_SOURCES
=
cursor.c listen.c rfbproto.c sockets.c vncviewer.c minilzo.c
libvncclient_la_SOURCES
=
cursor.c listen.c rfbproto.c sockets.c vncviewer.c minilzo.c
tls.c
noinst_HEADERS
=
lzoconf.h minilzo.h
noinst_HEADERS
=
lzoconf.h minilzo.h
tls.h
rfbproto.o
:
rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c
rfbproto.o
:
rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c
EXTRA_DIST
=
corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c
EXTRA_DIST
=
corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c
tls.c
$(libvncclient_la_OBJECTS)
:
../rfb/rfbclient.h
$(libvncclient_la_OBJECTS)
:
../rfb/rfbclient.h
...
...
libvncclient/rfbproto.c
View file @
f49a2927
...
@@ -53,6 +53,7 @@
...
@@ -53,6 +53,7 @@
#include <time.h>
#include <time.h>
#include "minilzo.h"
#include "minilzo.h"
#include "tls.h"
/*
/*
* rfbClientLog prints a time-stamped message to the log file (stderr).
* rfbClientLog prints a time-stamped message to the log file (stderr).
...
@@ -415,6 +416,7 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
...
@@ -415,6 +416,7 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
}
}
extern
void
rfbClientEncryptBytes
(
unsigned
char
*
bytes
,
char
*
passwd
);
extern
void
rfbClientEncryptBytes
(
unsigned
char
*
bytes
,
char
*
passwd
);
extern
void
rfbClientEncryptBytes2
(
unsigned
char
*
where
,
const
int
length
,
unsigned
char
*
key
);
rfbBool
rfbBool
rfbHandleAuthResult
(
rfbClient
*
client
)
rfbHandleAuthResult
(
rfbClient
*
client
)
...
@@ -456,6 +458,265 @@ rfbHandleAuthResult(rfbClient* client)
...
@@ -456,6 +458,265 @@ rfbHandleAuthResult(rfbClient* client)
return
FALSE
;
return
FALSE
;
}
}
static
void
ReadReason
(
rfbClient
*
client
)
{
uint32_t
reasonLen
;
char
*
reason
;
/* we have an error following */
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
reasonLen
,
4
))
return
;
reasonLen
=
rfbClientSwap32IfLE
(
reasonLen
);
reason
=
malloc
(
reasonLen
+
1
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
;
}
reason
[
reasonLen
]
=
0
;
rfbClientLog
(
"VNC connection failed: %s
\n
"
,
reason
);
free
(
reason
);
}
static
rfbBool
ReadSupportedSecurityType
(
rfbClient
*
client
,
uint32_t
*
result
,
rfbBool
subAuth
)
{
uint8_t
count
=
0
;
uint8_t
loop
=
0
;
uint8_t
flag
=
0
;
uint8_t
tAuth
[
256
];
char
buf1
[
500
],
buf2
[
10
];
uint32_t
authScheme
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
count
,
1
))
return
FALSE
;
if
(
count
==
0
)
{
rfbClientLog
(
"List of security types is ZERO, expecting an error to follow
\n
"
);
ReadReason
(
client
);
return
FALSE
;
}
if
(
count
>
sizeof
(
tAuth
))
{
rfbClientLog
(
"%d security types are too many; maximum is %d
\n
"
,
count
,
sizeof
(
tAuth
));
return
FALSE
;
}
rfbClientLog
(
"We have %d security types to read
\n
"
,
count
);
authScheme
=
0
;
/* now, we have a list of available security types to read ( uint8_t[] ) */
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
1
))
return
FALSE
;
rfbClientLog
(
"%d) Received security type %d
\n
"
,
loop
,
tAuth
[
loop
]);
if
(
flag
)
continue
;
if
(
tAuth
[
loop
]
==
rfbVncAuth
||
tAuth
[
loop
]
==
rfbNoAuth
||
tAuth
[
loop
]
==
rfbMSLogon
||
(
!
subAuth
&&
(
tAuth
[
loop
]
==
rfbTLS
||
tAuth
[
loop
]
==
rfbVeNCrypt
)))
{
flag
++
;
authScheme
=
tAuth
[
loop
];
rfbClientLog
(
"Selecting security type %d (%d/%d in the list)
\n
"
,
authScheme
,
loop
,
count
);
/* send back a single byte indicating which security type to use */
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
1
))
return
FALSE
;
}
}
if
(
authScheme
==
0
)
{
memset
(
buf1
,
0
,
sizeof
(
buf1
));
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
strlen
(
buf1
)
>=
sizeof
(
buf1
)
-
1
)
break
;
snprintf
(
buf2
,
sizeof
(
buf2
),
(
loop
>
0
?
", %d"
:
"%d"
),
(
int
)
tAuth
[
loop
]);
strncat
(
buf1
,
buf2
,
sizeof
(
buf1
)
-
strlen
(
buf1
)
-
1
);
}
rfbClientLog
(
"Unknown authentication scheme from VNC server: %s
\n
"
,
buf1
);
return
FALSE
;
}
*
result
=
authScheme
;
return
TRUE
;
}
static
rfbBool
HandleVncAuth
(
rfbClient
*
client
)
{
uint8_t
challenge
[
CHALLENGESIZE
];
char
*
passwd
=
NULL
;
int
i
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
challenge
,
CHALLENGESIZE
))
return
FALSE
;
if
(
client
->
serverPort
!=-
1
)
{
/* if not playing a vncrec file */
if
(
client
->
GetPassword
)
passwd
=
client
->
GetPassword
(
client
);
if
((
!
passwd
)
||
(
strlen
(
passwd
)
==
0
))
{
rfbClientLog
(
"Reading password failed
\n
"
);
return
FALSE
;
}
if
(
strlen
(
passwd
)
>
8
)
{
passwd
[
8
]
=
'\0'
;
}
rfbClientEncryptBytes
(
challenge
,
passwd
);
/* Lose the password from memory */
for
(
i
=
strlen
(
passwd
);
i
>=
0
;
i
--
)
{
passwd
[
i
]
=
'\0'
;
}
free
(
passwd
);
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
challenge
,
CHALLENGESIZE
))
return
FALSE
;
}
/* Handle the SecurityResult message */
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
return
TRUE
;
}
static
void
FreeUserCredential
(
rfbCredential
*
cred
)
{
if
(
cred
->
userCredential
.
username
)
free
(
cred
->
userCredential
.
username
);
if
(
cred
->
userCredential
.
password
)
free
(
cred
->
userCredential
.
password
);
free
(
cred
);
}
static
rfbBool
HandlePlainAuth
(
rfbClient
*
client
)
{
uint32_t
ulen
,
ulensw
;
uint32_t
plen
,
plensw
;
rfbCredential
*
cred
;
if
(
!
client
->
GetCredential
)
{
rfbClientLog
(
"GetCredential callback is not set.
\n
"
);
return
FALSE
;
}
cred
=
client
->
GetCredential
(
client
,
rfbCredentialTypeUser
);
if
(
!
cred
)
{
rfbClientLog
(
"Reading credential failed
\n
"
);
return
FALSE
;
}
ulen
=
(
cred
->
userCredential
.
username
?
strlen
(
cred
->
userCredential
.
username
)
:
0
);
ulensw
=
rfbClientSwap32IfLE
(
ulen
);
plen
=
(
cred
->
userCredential
.
password
?
strlen
(
cred
->
userCredential
.
password
)
:
0
);
plensw
=
rfbClientSwap32IfLE
(
plen
);
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
ulensw
,
4
)
||
!
WriteToRFBServer
(
client
,
(
char
*
)
&
plensw
,
4
))
{
FreeUserCredential
(
cred
);
return
FALSE
;
}
if
(
ulen
>
0
)
{
if
(
!
WriteToRFBServer
(
client
,
cred
->
userCredential
.
username
,
ulen
))
{
FreeUserCredential
(
cred
);
return
FALSE
;
}
}
if
(
plen
>
0
)
{
if
(
!
WriteToRFBServer
(
client
,
cred
->
userCredential
.
password
,
plen
))
{
FreeUserCredential
(
cred
);
return
FALSE
;
}
}
FreeUserCredential
(
cred
);
/* Handle the SecurityResult message */
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
return
TRUE
;
}
/* Simple 64bit big integer arithmetic implementation */
/* (x + y) % m, works even if (x + y) > 64bit */
#define rfbAddM64(x,y,m) ((x+y)%m+(x+y<x?(((uint64_t)-1)%m+1)%m:0))
/* (x * y) % m */
static
uint64_t
rfbMulM64
(
uint64_t
x
,
uint64_t
y
,
uint64_t
m
)
{
uint64_t
r
;
for
(
r
=
0
;
x
>
0
;
x
>>=
1
)
{
if
(
x
&
1
)
r
=
rfbAddM64
(
r
,
y
,
m
);
y
=
rfbAddM64
(
y
,
y
,
m
);
}
return
r
;
}
/* (x ^ y) % m */
static
uint64_t
rfbPowM64
(
uint64_t
b
,
uint64_t
e
,
uint64_t
m
)
{
uint64_t
r
;
for
(
r
=
1
;
e
>
0
;
e
>>=
1
)
{
if
(
e
&
1
)
r
=
rfbMulM64
(
r
,
b
,
m
);
b
=
rfbMulM64
(
b
,
b
,
m
);
}
return
r
;
}
static
rfbBool
HandleMSLogonAuth
(
rfbClient
*
client
)
{
uint64_t
gen
,
mod
,
resp
,
priv
,
pub
,
key
;
uint8_t
username
[
256
],
password
[
64
];
rfbCredential
*
cred
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
gen
,
8
))
return
FALSE
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
mod
,
8
))
return
FALSE
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
resp
,
8
))
return
FALSE
;
gen
=
rfbClientSwap64IfLE
(
gen
);
mod
=
rfbClientSwap64IfLE
(
mod
);
resp
=
rfbClientSwap64IfLE
(
resp
);
if
(
!
client
->
GetCredential
)
{
rfbClientLog
(
"GetCredential callback is not set.
\n
"
);
return
FALSE
;
}
rfbClientLog
(
"WARNING! MSLogon security type has very low password encryption! "
\
"Use it only with SSH tunnel or trusted network.
\n
"
);
cred
=
client
->
GetCredential
(
client
,
rfbCredentialTypeUser
);
if
(
!
cred
)
{
rfbClientLog
(
"Reading credential failed
\n
"
);
return
FALSE
;
}
memset
(
username
,
0
,
sizeof
(
username
));
strncpy
((
char
*
)
username
,
cred
->
userCredential
.
username
,
sizeof
(
username
));
memset
(
password
,
0
,
sizeof
(
password
));
strncpy
((
char
*
)
password
,
cred
->
userCredential
.
password
,
sizeof
(
password
));
FreeUserCredential
(
cred
);
srand
(
time
(
NULL
));
priv
=
((
uint64_t
)
rand
())
<<
32
;
priv
|=
(
uint64_t
)
rand
();
pub
=
rfbPowM64
(
gen
,
priv
,
mod
);
key
=
rfbPowM64
(
resp
,
priv
,
mod
);
pub
=
rfbClientSwap64IfLE
(
pub
);
key
=
rfbClientSwap64IfLE
(
key
);
rfbClientEncryptBytes2
(
username
,
sizeof
(
username
),
(
unsigned
char
*
)
&
key
);
rfbClientEncryptBytes2
(
password
,
sizeof
(
password
),
(
unsigned
char
*
)
&
key
);
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
pub
,
8
))
return
FALSE
;
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
username
,
sizeof
(
username
)))
return
FALSE
;
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
password
,
sizeof
(
password
)))
return
FALSE
;
/* Handle the SecurityResult message */
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
return
TRUE
;
}
/*
/*
* InitialiseRFBConnection.
* InitialiseRFBConnection.
...
@@ -466,11 +727,8 @@ InitialiseRFBConnection(rfbClient* client)
...
@@ -466,11 +727,8 @@ InitialiseRFBConnection(rfbClient* client)
{
{
rfbProtocolVersionMsg
pv
;
rfbProtocolVersionMsg
pv
;
int
major
,
minor
;
int
major
,
minor
;
uint32_t
authScheme
,
reasonLen
;
uint32_t
authScheme
;
char
*
reason
;
uint32_t
subAuthScheme
;
uint8_t
challenge
[
CHALLENGESIZE
];
char
*
passwd
=
NULL
;
int
i
;
rfbClientInitMsg
ci
;
rfbClientInitMsg
ci
;
/* if the connection is immediately closed, don't report anything, so
/* if the connection is immediately closed, don't report anything, so
...
@@ -530,64 +788,7 @@ InitialiseRFBConnection(rfbClient* client)
...
@@ -530,64 +788,7 @@ InitialiseRFBConnection(rfbClient* client)
/* 3.7 and onwards sends a # of security types first */
/* 3.7 and onwards sends a # of security types first */
if
(
client
->
major
==
3
&&
client
->
minor
>
6
)
if
(
client
->
major
==
3
&&
client
->
minor
>
6
)
{
{
uint8_t
count
=
0
;
if
(
!
ReadSupportedSecurityType
(
client
,
&
authScheme
,
FALSE
))
return
FALSE
;
uint8_t
loop
=
0
;
uint8_t
flag
=
0
;
uint8_t
tAuth
[
256
];
char
buf1
[
500
],
buf2
[
10
];
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
count
,
1
))
return
FALSE
;
if
(
count
==
0
)
{
rfbClientLog
(
"List of security types is ZERO, expecting an error to follow
\n
"
);
/* we have an error following */
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
reasonLen
,
4
))
return
FALSE
;
reasonLen
=
rfbClientSwap32IfLE
(
reasonLen
);
reason
=
malloc
(
reasonLen
+
1
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
FALSE
;
}
reason
[
reasonLen
]
=
0
;
rfbClientLog
(
"VNC connection failed: %s
\n
"
,
reason
);
free
(
reason
);
return
FALSE
;
}
if
(
count
>
sizeof
(
tAuth
))
{
rfbClientLog
(
"%d security types are too many; maximum is %d
\n
"
,
count
,
sizeof
(
tAuth
));
return
FALSE
;
}
rfbClientLog
(
"We have %d security types to read
\n
"
,
count
);
authScheme
=
0
;
/* now, we have a list of available security types to read ( uint8_t[] ) */
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
1
))
return
FALSE
;
rfbClientLog
(
"%d) Received security type %d
\n
"
,
loop
,
tAuth
[
loop
]);
if
((
flag
==
0
)
&&
((
tAuth
[
loop
]
==
rfbVncAuth
)
||
(
tAuth
[
loop
]
==
rfbNoAuth
)))
{
flag
++
;
authScheme
=
tAuth
[
loop
];
rfbClientLog
(
"Selecting security type %d (%d/%d in the list)
\n
"
,
authScheme
,
loop
,
count
);
/* send back a single byte indicating which security type to use */
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
1
))
return
FALSE
;
}
}
if
(
authScheme
==
0
)
{
memset
(
buf1
,
0
,
sizeof
(
buf1
));
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
strlen
(
buf1
)
>=
sizeof
(
buf1
)
-
1
)
break
;
snprintf
(
buf2
,
sizeof
(
buf2
),
(
loop
>
0
?
", %d"
:
"%d"
),
(
int
)
tAuth
[
loop
]);
strncat
(
buf1
,
buf2
,
sizeof
(
buf1
)
-
strlen
(
buf1
)
-
1
);
}
rfbClientLog
(
"Unknown authentication scheme from VNC server: %s
\n
"
,
buf1
);
return
FALSE
;
}
}
}
else
else
{
{
...
@@ -596,19 +797,12 @@ InitialiseRFBConnection(rfbClient* client)
...
@@ -596,19 +797,12 @@ InitialiseRFBConnection(rfbClient* client)
}
}
rfbClientLog
(
"Selected Security Scheme %d
\n
"
,
authScheme
);
rfbClientLog
(
"Selected Security Scheme %d
\n
"
,
authScheme
);
client
->
authScheme
=
authScheme
;
switch
(
authScheme
)
{
switch
(
authScheme
)
{
case
rfbConnFailed
:
case
rfbConnFailed
:
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
reasonLen
,
4
))
return
FALSE
;
ReadReason
(
client
);
reasonLen
=
rfbClientSwap32IfLE
(
reasonLen
);
reason
=
malloc
(
reasonLen
+
1
);
if
(
!
ReadFromRFBServer
(
client
,
reason
,
reasonLen
))
{
free
(
reason
);
return
FALSE
;
}
reason
[
reasonLen
]
=
0
;
rfbClientLog
(
"VNC connection failed: %s
\n
"
,
reason
);
free
(
reason
);
return
FALSE
;
return
FALSE
;
case
rfbNoAuth
:
case
rfbNoAuth
:
...
@@ -621,35 +815,73 @@ InitialiseRFBConnection(rfbClient* client)
...
@@ -621,35 +815,73 @@ InitialiseRFBConnection(rfbClient* client)
break
;
break
;
case
rfbVncAuth
:
case
rfbVncAuth
:
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
challenge
,
CHALLENGESIZE
))
return
FALSE
;
if
(
!
HandleVncAuth
(
client
))
return
FALSE
;
break
;
if
(
client
->
serverPort
!=-
1
)
{
/* if not playing a vncrec file */
case
rfbMSLogon
:
if
(
client
->
GetPassword
)
if
(
!
HandleMSLogonAuth
(
client
))
return
FALSE
;
passwd
=
client
->
GetPassword
(
client
)
;
break
;
if
((
!
passwd
)
||
(
strlen
(
passwd
)
==
0
))
{
case
rfbTLS
:
rfbClientLog
(
"Reading password failed
\n
"
);
if
(
!
HandleAnonTLSAuth
(
client
))
return
FALSE
;
/* After the TLS session is established, sub auth types are expected.
* Note that all following reading/writing are through the TLS session from here.
*/
if
(
!
ReadSupportedSecurityType
(
client
,
&
subAuthScheme
,
TRUE
))
return
FALSE
;
client
->
subAuthScheme
=
subAuthScheme
;
switch
(
subAuthScheme
)
{
case
rfbConnFailed
:
ReadReason
(
client
);
return
FALSE
;
return
FALSE
;
}
if
(
strlen
(
passwd
)
>
8
)
{
passwd
[
8
]
=
'\0'
;
}
rfbClientEncryptBytes
(
challenge
,
passwd
);
case
rfbNoAuth
:
rfbClientLog
(
"No sub authentication needed
\n
"
);
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
break
;
/* Lose the password from memory */
case
rfbVncAuth
:
for
(
i
=
strlen
(
passwd
);
i
>=
0
;
i
--
)
{
if
(
!
HandleVncAuth
(
client
))
return
FALSE
;
passwd
[
i
]
=
'\0'
;
break
;
}
free
(
passwd
);
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
challenge
,
CHALLENGESIZE
))
return
FALSE
;
default:
rfbClientLog
(
"Unknown sub authentication scheme from VNC server: %d
\n
"
,
(
int
)
subAuthScheme
);
return
FALSE
;
}
}
/* Handle the SecurityResult message */
break
;
case
rfbVeNCrypt
:
if
(
!
HandleVeNCryptAuth
(
client
))
return
FALSE
;
switch
(
client
->
subAuthScheme
)
{
case
rfbVeNCryptTLSNone
:
case
rfbVeNCryptX509None
:
rfbClientLog
(
"No sub authentication needed
\n
"
);
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
if
(
!
rfbHandleAuthResult
(
client
))
return
FALSE
;
break
;
break
;
case
rfbVeNCryptTLSVNC
:
case
rfbVeNCryptX509VNC
:
if
(
!
HandleVncAuth
(
client
))
return
FALSE
;
break
;
case
rfbVeNCryptTLSPlain
:
case
rfbVeNCryptX509Plain
:
if
(
!
HandlePlainAuth
(
client
))
return
FALSE
;
break
;
default:
rfbClientLog
(
"Unknown sub authentication scheme from VNC server: %d
\n
"
,
client
->
subAuthScheme
);
return
FALSE
;
}
break
;
default:
default:
rfbClientLog
(
"Unknown authentication scheme from VNC server: %d
\n
"
,
rfbClientLog
(
"Unknown authentication scheme from VNC server: %d
\n
"
,
(
int
)
authScheme
);
(
int
)
authScheme
);
...
@@ -1769,6 +2001,7 @@ PrintPixelFormat(rfbPixelFormat *format)
...
@@ -1769,6 +2001,7 @@ PrintPixelFormat(rfbPixelFormat *format)
/* avoid name clashes with LibVNCServer */
/* avoid name clashes with LibVNCServer */
#define rfbEncryptBytes rfbClientEncryptBytes
#define rfbEncryptBytes rfbClientEncryptBytes
#define rfbEncryptBytes2 rfbClientEncryptBytes2
#define rfbDes rfbClientDes
#define rfbDes rfbClientDes
#define rfbDesKey rfbClientDesKey
#define rfbDesKey rfbClientDesKey
#define rfbUseKey rfbClientUseKey
#define rfbUseKey rfbClientUseKey
...
...
libvncclient/sockets.c
View file @
f49a2927
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netdb.h>
#endif
#endif
#include "tls.h"
void
PrintInHex
(
char
*
buf
,
int
len
);
void
PrintInHex
(
char
*
buf
,
int
len
);
...
@@ -128,7 +129,16 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
...
@@ -128,7 +129,16 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
if
(
n
<=
RFB_BUF_SIZE
)
{
if
(
n
<=
RFB_BUF_SIZE
)
{
while
(
client
->
buffered
<
n
)
{
while
(
client
->
buffered
<
n
)
{
int
i
=
read
(
client
->
sock
,
client
->
buf
+
client
->
buffered
,
RFB_BUF_SIZE
-
client
->
buffered
);
int
i
;
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
if
(
client
->
tlsSession
)
{
i
=
ReadFromTLS
(
client
,
client
->
buf
+
client
->
buffered
,
RFB_BUF_SIZE
-
client
->
buffered
);
}
else
{
#endif
i
=
read
(
client
->
sock
,
client
->
buf
+
client
->
buffered
,
RFB_BUF_SIZE
-
client
->
buffered
);
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
}
#endif
if
(
i
<=
0
)
{
if
(
i
<=
0
)
{
if
(
i
<
0
)
{
if
(
i
<
0
)
{
#ifdef WIN32
#ifdef WIN32
...
@@ -160,7 +170,16 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
...
@@ -160,7 +170,16 @@ ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
}
else
{
}
else
{
while
(
n
>
0
)
{
while
(
n
>
0
)
{
int
i
=
read
(
client
->
sock
,
out
,
n
);
int
i
;
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
if
(
client
->
tlsSession
)
{
i
=
ReadFromTLS
(
client
,
out
,
n
);
}
else
{
#endif
i
=
read
(
client
->
sock
,
out
,
n
);
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
}
#endif
if
(
i
<=
0
)
{
if
(
i
<=
0
)
{
if
(
i
<
0
)
{
if
(
i
<
0
)
{
#ifdef WIN32
#ifdef WIN32
...
@@ -214,6 +233,16 @@ WriteToRFBServer(rfbClient* client, char *buf, int n)
...
@@ -214,6 +233,16 @@ WriteToRFBServer(rfbClient* client, char *buf, int n)
if
(
client
->
serverPort
==-
1
)
if
(
client
->
serverPort
==-
1
)
return
TRUE
;
/* vncrec playing */
return
TRUE
;
/* vncrec playing */
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
if
(
client
->
tlsSession
)
{
/* WriteToTLS() will guarantee either everything is written, or error/eof returns */
i
=
WriteToTLS
(
client
,
buf
,
n
);
if
(
i
<=
0
)
return
FALSE
;
return
TRUE
;
}
#endif
while
(
i
<
n
)
{
while
(
i
<
n
)
{
j
=
write
(
client
->
sock
,
buf
+
i
,
(
n
-
i
));
j
=
write
(
client
->
sock
,
buf
+
i
,
(
n
-
i
));
if
(
j
<=
0
)
{
if
(
j
<=
0
)
{
...
...
libvncclient/tls.c
0 → 100644
View file @
f49a2927
/*
* Copyright (C) 2009 Vic Lee.
*
* 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.
*/
#include <rfb/rfbclient.h>
#include <errno.h>
#include "tls.h"
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
static
const
int
rfbCertTypePriority
[]
=
{
GNUTLS_CRT_X509
,
0
};
static
const
int
rfbProtoPriority
[]
=
{
GNUTLS_TLS1_1
,
GNUTLS_TLS1_0
,
GNUTLS_SSL3
,
0
};
static
const
int
rfbKXPriority
[]
=
{
GNUTLS_KX_DHE_DSS
,
GNUTLS_KX_RSA
,
GNUTLS_KX_DHE_RSA
,
GNUTLS_KX_SRP
,
0
};
static
const
int
rfbKXAnon
[]
=
{
GNUTLS_KX_ANON_DH
,
0
};
#define DH_BITS 1024
static
gnutls_dh_params_t
rfbDHParams
;
static
rfbBool
rfbTLSInitialized
=
FALSE
;
static
rfbBool
InitializeTLS
(
void
)
{
int
ret
;
if
(
rfbTLSInitialized
)
return
TRUE
;
if
((
ret
=
gnutls_global_init
())
<
0
||
(
ret
=
gnutls_dh_params_init
(
&
rfbDHParams
))
<
0
||
(
ret
=
gnutls_dh_params_generate2
(
rfbDHParams
,
DH_BITS
))
<
0
)
{
rfbClientLog
(
"Failed to initialized GnuTLS: %s.
\n
"
,
gnutls_strerror
(
ret
));
return
FALSE
;
}
rfbClientLog
(
"GnuTLS initialized.
\n
"
);
rfbTLSInitialized
=
TRUE
;
return
TRUE
;
}
static
ssize_t
PushTLS
(
gnutls_transport_ptr_t
transport
,
const
void
*
data
,
size_t
len
)
{
rfbClient
*
client
=
(
rfbClient
*
)
transport
;
int
ret
;
while
(
1
)
{
ret
=
write
(
client
->
sock
,
data
,
len
);
if
(
ret
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
return
-
1
;
}
return
ret
;
}
}
static
ssize_t
PullTLS
(
gnutls_transport_ptr_t
transport
,
void
*
data
,
size_t
len
)
{
rfbClient
*
client
=
(
rfbClient
*
)
transport
;
int
ret
;
while
(
1
)
{
ret
=
read
(
client
->
sock
,
data
,
len
);
if
(
ret
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
return
-
1
;
}
return
ret
;
}
}
static
rfbBool
InitializeTLSSession
(
rfbClient
*
client
,
rfbBool
anonTLS
)
{
int
ret
;
if
(
client
->
tlsSession
)
return
TRUE
;
if
((
ret
=
gnutls_init
(
&
client
->
tlsSession
,
GNUTLS_CLIENT
))
<
0
)
{
rfbClientLog
(
"Failed to initialized TLS session: %s.
\n
"
,
gnutls_strerror
(
ret
));
return
FALSE
;
}
if
((
ret
=
gnutls_set_default_priority
(
client
->
tlsSession
))
<
0
||
(
ret
=
gnutls_kx_set_priority
(
client
->
tlsSession
,
anonTLS
?
rfbKXAnon
:
rfbKXPriority
))
<
0
||
(
ret
=
gnutls_certificate_type_set_priority
(
client
->
tlsSession
,
rfbCertTypePriority
))
<
0
||
(
ret
=
gnutls_protocol_set_priority
(
client
->
tlsSession
,
rfbProtoPriority
))
<
0
)
{
FreeTLS
(
client
);
rfbClientLog
(
"Failed to set TLS priority: %s.
\n
"
,
gnutls_strerror
(
ret
));
return
FALSE
;
}
gnutls_transport_set_ptr
(
client
->
tlsSession
,
(
gnutls_transport_ptr_t
)
client
);
gnutls_transport_set_push_function
(
client
->
tlsSession
,
PushTLS
);
gnutls_transport_set_pull_function
(
client
->
tlsSession
,
PullTLS
);
rfbClientLog
(
"TLS session initialized.
\n
"
);
return
TRUE
;
}
static
rfbBool
SetTLSAnonCredential
(
rfbClient
*
client
)
{
gnutls_anon_client_credentials
anonCred
;
int
ret
;
if
((
ret
=
gnutls_anon_allocate_client_credentials
(
&
anonCred
))
<
0
||
(
ret
=
gnutls_credentials_set
(
client
->
tlsSession
,
GNUTLS_CRD_ANON
,
anonCred
))
<
0
)
{
FreeTLS
(
client
);
rfbClientLog
(
"Failed to create anonymous credentials: %s"
,
gnutls_strerror
(
ret
));
return
FALSE
;
}
rfbClientLog
(
"TLS anonymous credential created.
\n
"
);
return
TRUE
;
}
static
rfbBool
HandshakeTLS
(
rfbClient
*
client
)
{
int
timeout
=
15
;
int
ret
;
while
(
timeout
>
0
&&
(
ret
=
gnutls_handshake
(
client
->
tlsSession
))
<
0
)
{
if
(
!
gnutls_error_is_fatal
(
ret
))
{
rfbClientLog
(
"TLS handshake blocking.
\n
"
);
sleep
(
1
);
timeout
--
;
continue
;
}
rfbClientLog
(
"TLS handshake failed: %s.
\n
"
,
gnutls_strerror
(
ret
));
FreeTLS
(
client
);
return
FALSE
;
}
if
(
timeout
<=
0
)
{
rfbClientLog
(
"TLS handshake timeout.
\n
"
);
FreeTLS
(
client
);
return
FALSE
;
}
rfbClientLog
(
"TLS handshake done.
\n
"
);
return
TRUE
;
}
/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */
static
rfbBool
ReadVeNCryptSecurityType
(
rfbClient
*
client
,
uint32_t
*
result
)
{
uint8_t
count
=
0
;
uint8_t
loop
=
0
;
uint8_t
flag
=
0
;
uint32_t
tAuth
[
256
],
t
;
char
buf1
[
500
],
buf2
[
10
];
uint32_t
authScheme
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
count
,
1
))
return
FALSE
;
if
(
count
==
0
)
{
rfbClientLog
(
"List of security types is ZERO. Giving up.
\n
"
);
return
FALSE
;
}
if
(
count
>
sizeof
(
tAuth
))
{
rfbClientLog
(
"%d security types are too many; maximum is %d
\n
"
,
count
,
sizeof
(
tAuth
));
return
FALSE
;
}
rfbClientLog
(
"We have %d security types to read
\n
"
,
count
);
authScheme
=
0
;
/* now, we have a list of available security types to read ( uint8_t[] ) */
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
4
))
return
FALSE
;
t
=
rfbClientSwap32IfLE
(
tAuth
[
loop
]);
rfbClientLog
(
"%d) Received security type %d
\n
"
,
loop
,
t
);
if
(
flag
)
continue
;
if
(
t
==
rfbVeNCryptTLSNone
||
t
==
rfbVeNCryptTLSVNC
||
t
==
rfbVeNCryptTLSPlain
||
t
==
rfbVeNCryptX509None
||
t
==
rfbVeNCryptX509VNC
||
t
==
rfbVeNCryptX509Plain
)
{
flag
++
;
authScheme
=
t
;
rfbClientLog
(
"Selecting security type %d (%d/%d in the list)
\n
"
,
authScheme
,
loop
,
count
);
/* send back 4 bytes (in original byte order!) indicating which security type to use */
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
tAuth
[
loop
],
4
))
return
FALSE
;
}
tAuth
[
loop
]
=
t
;
}
if
(
authScheme
==
0
)
{
memset
(
buf1
,
0
,
sizeof
(
buf1
));
for
(
loop
=
0
;
loop
<
count
;
loop
++
)
{
if
(
strlen
(
buf1
)
>=
sizeof
(
buf1
)
-
1
)
break
;
snprintf
(
buf2
,
sizeof
(
buf2
),
(
loop
>
0
?
", %d"
:
"%d"
),
(
int
)
tAuth
[
loop
]);
strncat
(
buf1
,
buf2
,
sizeof
(
buf1
)
-
strlen
(
buf1
)
-
1
);
}
rfbClientLog
(
"Unknown VeNCrypt authentication scheme from VNC server: %s
\n
"
,
buf1
);
return
FALSE
;
}
*
result
=
authScheme
;
return
TRUE
;
}
static
void
FreeX509Credential
(
rfbCredential
*
cred
)
{
if
(
cred
->
x509Credential
.
x509CACertFile
)
free
(
cred
->
x509Credential
.
x509CACertFile
);
if
(
cred
->
x509Credential
.
x509CACrlFile
)
free
(
cred
->
x509Credential
.
x509CACrlFile
);
if
(
cred
->
x509Credential
.
x509ClientCertFile
)
free
(
cred
->
x509Credential
.
x509ClientCertFile
);
if
(
cred
->
x509Credential
.
x509ClientKeyFile
)
free
(
cred
->
x509Credential
.
x509ClientKeyFile
);
free
(
cred
);
}
static
gnutls_certificate_credentials_t
CreateX509CertCredential
(
rfbCredential
*
cred
)
{
gnutls_certificate_credentials_t
x509_cred
;
int
ret
;
if
(
!
cred
->
x509Credential
.
x509CACertFile
)
{
rfbClientLog
(
"No CA certificate provided.
\n
"
);
return
NULL
;
}
if
((
ret
=
gnutls_certificate_allocate_credentials
(
&
x509_cred
))
<
0
)
{
rfbClientLog
(
"Cannot allocate credentials: %s.
\n
"
,
gnutls_strerror
(
ret
));
return
NULL
;
}
if
((
ret
=
gnutls_certificate_set_x509_trust_file
(
x509_cred
,
cred
->
x509Credential
.
x509CACertFile
,
GNUTLS_X509_FMT_PEM
))
<
0
)
{
rfbClientLog
(
"Cannot load CA credentials: %s.
\n
"
,
gnutls_strerror
(
ret
));
gnutls_certificate_free_credentials
(
x509_cred
);
return
NULL
;
}
if
(
cred
->
x509Credential
.
x509ClientCertFile
&&
cred
->
x509Credential
.
x509ClientKeyFile
)
{
if
((
ret
=
gnutls_certificate_set_x509_key_file
(
x509_cred
,
cred
->
x509Credential
.
x509ClientCertFile
,
cred
->
x509Credential
.
x509ClientKeyFile
,
GNUTLS_X509_FMT_PEM
))
<
0
)
{
rfbClientLog
(
"Cannot load client certificate or key: %s.
\n
"
,
gnutls_strerror
(
ret
));
gnutls_certificate_free_credentials
(
x509_cred
);
return
NULL
;
}
}
else
{
rfbClientLog
(
"No client certificate or key provided.
\n
"
);
}
if
(
cred
->
x509Credential
.
x509CACrlFile
)
{
if
((
ret
=
gnutls_certificate_set_x509_crl_file
(
x509_cred
,
cred
->
x509Credential
.
x509CACrlFile
,
GNUTLS_X509_FMT_PEM
))
<
0
)
{
rfbClientLog
(
"Cannot load CRL: %s.
\n
"
,
gnutls_strerror
(
ret
));
gnutls_certificate_free_credentials
(
x509_cred
);
return
NULL
;
}
}
else
{
rfbClientLog
(
"No CRL provided.
\n
"
);
}
gnutls_certificate_set_dh_params
(
x509_cred
,
rfbDHParams
);
return
x509_cred
;
}
#endif
rfbBool
HandleAnonTLSAuth
(
rfbClient
*
client
)
{
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
if
(
!
InitializeTLS
()
||
!
InitializeTLSSession
(
client
,
TRUE
))
return
FALSE
;
if
(
!
SetTLSAnonCredential
(
client
))
return
FALSE
;
if
(
!
HandshakeTLS
(
client
))
return
FALSE
;
return
TRUE
;
#else
rfbClientLog
(
"TLS is not supported.
\n
"
);
return
FALSE
;
#endif
}
rfbBool
HandleVeNCryptAuth
(
rfbClient
*
client
)
{
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
uint8_t
major
,
minor
,
status
;
uint32_t
authScheme
;
rfbBool
anonTLS
;
gnutls_certificate_credentials_t
x509_cred
=
NULL
;
int
ret
;
if
(
!
InitializeTLS
())
return
FALSE
;
/* Read VeNCrypt version */
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
major
,
1
)
||
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
minor
,
1
))
{
return
FALSE
;
}
rfbClientLog
(
"Got VeNCrypt version %d.%d from server.
\n
"
,
(
int
)
major
,
(
int
)
minor
);
if
(
major
!=
0
&&
minor
!=
2
)
{
rfbClientLog
(
"Unsupported VeNCrypt version.
\n
"
);
return
FALSE
;
}
if
(
!
WriteToRFBServer
(
client
,
(
char
*
)
&
major
,
1
)
||
!
WriteToRFBServer
(
client
,
(
char
*
)
&
minor
,
1
)
||
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
status
,
1
))
{
return
FALSE
;
}
if
(
status
!=
0
)
{
rfbClientLog
(
"Server refused VeNCrypt version %d.%d.
\n
"
,
(
int
)
major
,
(
int
)
minor
);
return
FALSE
;
}
if
(
!
ReadVeNCryptSecurityType
(
client
,
&
authScheme
))
return
FALSE
;
if
(
!
ReadFromRFBServer
(
client
,
(
char
*
)
&
status
,
1
)
||
status
!=
1
)
{
rfbClientLog
(
"Server refused VeNCrypt authentication %d (%d).
\n
"
,
authScheme
,
(
int
)
status
);
return
FALSE
;
}
client
->
subAuthScheme
=
authScheme
;
/* Some VeNCrypt security types are anonymous TLS, others are X509 */
switch
(
authScheme
)
{
case
rfbVeNCryptTLSNone
:
case
rfbVeNCryptTLSVNC
:
case
rfbVeNCryptTLSPlain
:
anonTLS
=
TRUE
;
break
;
default:
anonTLS
=
FALSE
;
break
;
}
/* Get X509 Credentials if it's not anonymous */
if
(
!
anonTLS
)
{
rfbCredential
*
cred
;
if
(
!
client
->
GetCredential
)
{
rfbClientLog
(
"GetCredential callback is not set.
\n
"
);
return
FALSE
;
}
cred
=
client
->
GetCredential
(
client
,
rfbCredentialTypeX509
);
if
(
!
cred
)
{
rfbClientLog
(
"Reading credential failed
\n
"
);
return
FALSE
;
}
x509_cred
=
CreateX509CertCredential
(
cred
);
FreeX509Credential
(
cred
);
if
(
!
x509_cred
)
return
FALSE
;
}
/* Start up the TLS session */
if
(
!
InitializeTLSSession
(
client
,
anonTLS
))
return
FALSE
;
if
(
anonTLS
)
{
if
(
!
SetTLSAnonCredential
(
client
))
return
FALSE
;
}
else
{
if
((
ret
=
gnutls_credentials_set
(
client
->
tlsSession
,
GNUTLS_CRD_CERTIFICATE
,
x509_cred
))
<
0
)
{
rfbClientLog
(
"Cannot set x509 credential: %s.
\n
"
,
gnutls_strerror
(
ret
));
FreeTLS
(
client
);
return
FALSE
;
}
}
if
(
!
HandshakeTLS
(
client
))
return
FALSE
;
/* TODO: validate certificate */
/* We are done here. The caller should continue with client->subAuthScheme
* to do actual sub authentication.
*/
return
TRUE
;
#else
rfbClientLog
(
"TLS is not supported.
\n
"
);
return
FALSE
;
#endif
}
int
ReadFromTLS
(
rfbClient
*
client
,
char
*
out
,
unsigned
int
n
)
{
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
ssize_t
ret
;
ret
=
gnutls_record_recv
(
client
->
tlsSession
,
out
,
n
);
if
(
ret
>=
0
)
return
ret
;
if
(
ret
==
GNUTLS_E_REHANDSHAKE
||
ret
==
GNUTLS_E_AGAIN
)
{
errno
=
EAGAIN
;
}
else
{
rfbClientLog
(
"Error reading from TLS: %s.
\n
"
,
gnutls_strerror
(
ret
));
errno
=
EINTR
;
}
return
-
1
;
#else
rfbClientLog
(
"TLS is not supported.
\n
"
);
errno
=
EINTR
;
return
-
1
;
#endif
}
int
WriteToTLS
(
rfbClient
*
client
,
char
*
buf
,
unsigned
int
n
)
{
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
unsigned
int
offset
=
0
;
ssize_t
ret
;
while
(
offset
<
n
)
{
ret
=
gnutls_record_send
(
client
->
tlsSession
,
buf
+
offset
,
(
size_t
)(
n
-
offset
));
if
(
ret
==
0
)
continue
;
if
(
ret
<
0
)
{
if
(
ret
==
GNUTLS_E_AGAIN
||
ret
==
GNUTLS_E_INTERRUPTED
)
continue
;
rfbClientLog
(
"Error writing to TLS: %s.
\n
"
,
gnutls_strerror
(
ret
));
return
-
1
;
}
offset
+=
(
unsigned
int
)
ret
;
}
return
offset
;
#else
rfbClientLog
(
"TLS is not supported.
\n
"
);
errno
=
EINTR
;
return
-
1
;
#endif
}
void
FreeTLS
(
rfbClient
*
client
)
{
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
if
(
client
->
tlsSession
)
{
gnutls_deinit
(
client
->
tlsSession
);
client
->
tlsSession
=
NULL
;
}
#endif
}
libvncclient/tls.h
0 → 100644
View file @
f49a2927
#ifndef TLS_H
#define TLS_H
/*
* Copyright (C) 2009 Vic Lee.
*
* 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.
*/
/* Handle Anonymous TLS Authentication (18) with the server.
* After authentication, client->tlsSession will be set.
*/
rfbBool
HandleAnonTLSAuth
(
rfbClient
*
client
);
/* Handle VeNCrypt Authentication (19) with the server.
* The callback function GetX509Credential will be called.
* After authentication, client->tlsSession will be set.
*/
rfbBool
HandleVeNCryptAuth
(
rfbClient
*
client
);
/* Read desired bytes from TLS session.
* It's a wrapper function over gnutls_record_recv() and return values
* are same as read(), that is, >0 for actual bytes read, 0 for EOF,
* or EAGAIN, EINTR.
* This should be a non-blocking call. Blocking is handled in sockets.c.
*/
int
ReadFromTLS
(
rfbClient
*
client
,
char
*
out
,
unsigned
int
n
);
/* Write desired bytes to TLS session.
* It's a wrapper function over gnutls_record_send() and it will be
* blocking call, until all bytes are written or error returned.
*/
int
WriteToTLS
(
rfbClient
*
client
,
char
*
buf
,
unsigned
int
n
);
/* Free TLS resources */
void
FreeTLS
(
rfbClient
*
client
);
#endif
/* TLS_H */
libvncclient/vncviewer.c
View file @
f49a2927
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#include <string.h>
#include <string.h>
#include <time.h>
#include <time.h>
#include <rfb/rfbclient.h>
#include <rfb/rfbclient.h>
#include "tls.h"
static
void
Dummy
(
rfbClient
*
client
)
{
static
void
Dummy
(
rfbClient
*
client
)
{
}
}
...
@@ -181,6 +182,13 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
...
@@ -181,6 +182,13 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client
->
CurrentKeyboardLedState
=
0
;
client
->
CurrentKeyboardLedState
=
0
;
client
->
HandleKeyboardLedState
=
(
HandleKeyboardLedStateProc
)
DummyPoint
;
client
->
HandleKeyboardLedState
=
(
HandleKeyboardLedStateProc
)
DummyPoint
;
client
->
authScheme
=
0
;
client
->
subAuthScheme
=
0
;
client
->
GetCredential
=
NULL
;
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
client
->
tlsSession
=
NULL
;
#endif
return
client
;
return
client
;
}
}
...
@@ -323,6 +331,7 @@ void rfbClientCleanup(rfbClient* client) {
...
@@ -323,6 +331,7 @@ void rfbClientCleanup(rfbClient* client) {
#endif
#endif
#endif
#endif
FreeTLS
(
client
);
if
(
client
->
sock
>
0
)
if
(
client
->
sock
>
0
)
close
(
client
->
sock
);
close
(
client
->
sock
);
free
(
client
->
desktopName
);
free
(
client
->
desktopName
);
...
...
libvncserver/vncauth.c
View file @
f49a2927
...
@@ -191,3 +191,18 @@ rfbEncryptBytes(unsigned char *bytes, char *passwd)
...
@@ -191,3 +191,18 @@ rfbEncryptBytes(unsigned char *bytes, char *passwd)
rfbDes
(
bytes
+
i
,
bytes
+
i
);
rfbDes
(
bytes
+
i
,
bytes
+
i
);
}
}
}
}
void
rfbEncryptBytes2
(
unsigned
char
*
where
,
const
int
length
,
unsigned
char
*
key
)
{
int
i
,
j
;
rfbDesKey
(
key
,
EN0
);
for
(
i
=
0
;
i
<
8
;
i
++
)
where
[
i
]
^=
key
[
i
];
rfbDes
(
where
,
where
);
for
(
i
=
8
;
i
<
length
;
i
+=
8
)
{
for
(
j
=
0
;
j
<
8
;
j
++
)
where
[
i
+
j
]
^=
where
[
i
+
j
-
8
];
rfbDes
(
where
+
i
,
where
+
i
);
}
}
rfb/rfbclient.h
View file @
f49a2927
...
@@ -33,6 +33,9 @@
...
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <unistd.h>
#include <rfb/rfbproto.h>
#include <rfb/rfbproto.h>
#include <rfb/keysym.h>
#include <rfb/keysym.h>
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
#include <gnutls/gnutls.h>
#endif
#define rfbClientSwap16IfLE(s) \
#define rfbClientSwap16IfLE(s) \
(*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
(*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
...
@@ -43,6 +46,16 @@
...
@@ -43,6 +46,16 @@
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
(((l) & 0x000000ff) << 24)) : (l))
#define rfbClientSwap64IfLE(l) \
(*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \
(((l) & 0x00ff000000000000ULL) >> 40) | \
(((l) & 0x0000ff0000000000ULL) >> 24) | \
(((l) & 0x000000ff00000000ULL) >> 8) | \
(((l) & 0x00000000ff000000ULL) << 8) | \
(((l) & 0x0000000000ff0000ULL) << 24) | \
(((l) & 0x000000000000ff00ULL) << 40) | \
(((l) & 0x00000000000000ffULL) << 56)) : (l))
#define FLASH_PORT_OFFSET 5400
#define FLASH_PORT_OFFSET 5400
#define LISTEN_PORT_OFFSET 5500
#define LISTEN_PORT_OFFSET 5500
#define TUNNEL_PORT_OFFSET 5500
#define TUNNEL_PORT_OFFSET 5500
...
@@ -98,6 +111,27 @@ typedef struct {
...
@@ -98,6 +111,27 @@ typedef struct {
int
scaleSetting
;
/* 0 means no scale set, else 1/scaleSetting */
int
scaleSetting
;
/* 0 means no scale set, else 1/scaleSetting */
}
AppData
;
}
AppData
;
/* For GetCredentialProc callback function to return */
typedef
union
_rfbCredential
{
/* X509 (VeNCrypt) */
struct
{
char
*
x509CACertFile
;
char
*
x509CACrlFile
;
char
*
x509ClientCertFile
;
char
*
x509ClientKeyFile
;
}
x509Credential
;
/* Plain (VeNCrypt), MSLogon (UltraVNC) */
struct
{
char
*
username
;
char
*
password
;
}
userCredential
;
}
rfbCredential
;
#define rfbCredentialTypeX509 1
#define rfbCredentialTypeUser 2
struct
_rfbClient
;
struct
_rfbClient
;
...
@@ -109,6 +143,7 @@ typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client);
...
@@ -109,6 +143,7 @@ typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client);
typedef
void
(
*
GotFrameBufferUpdateProc
)(
struct
_rfbClient
*
client
,
int
x
,
int
y
,
int
w
,
int
h
);
typedef
void
(
*
GotFrameBufferUpdateProc
)(
struct
_rfbClient
*
client
,
int
x
,
int
y
,
int
w
,
int
h
);
typedef
void
(
*
FinishedFrameBufferUpdateProc
)(
struct
_rfbClient
*
client
);
typedef
void
(
*
FinishedFrameBufferUpdateProc
)(
struct
_rfbClient
*
client
);
typedef
char
*
(
*
GetPasswordProc
)(
struct
_rfbClient
*
client
);
typedef
char
*
(
*
GetPasswordProc
)(
struct
_rfbClient
*
client
);
typedef
rfbCredential
*
(
*
GetCredentialProc
)(
struct
_rfbClient
*
client
,
int
credentialType
);
typedef
rfbBool
(
*
MallocFrameBufferProc
)(
struct
_rfbClient
*
client
);
typedef
rfbBool
(
*
MallocFrameBufferProc
)(
struct
_rfbClient
*
client
);
typedef
void
(
*
GotXCutTextProc
)(
struct
_rfbClient
*
client
,
const
char
*
text
,
int
textlen
);
typedef
void
(
*
GotXCutTextProc
)(
struct
_rfbClient
*
client
,
const
char
*
text
,
int
textlen
);
typedef
void
(
*
BellProc
)(
struct
_rfbClient
*
client
);
typedef
void
(
*
BellProc
)(
struct
_rfbClient
*
client
);
...
@@ -254,6 +289,22 @@ typedef struct _rfbClient {
...
@@ -254,6 +289,22 @@ typedef struct _rfbClient {
/* negotiated protocol version */
/* negotiated protocol version */
int
major
,
minor
;
int
major
,
minor
;
/* The selected security types */
uint32_t
authScheme
,
subAuthScheme
;
#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
/* The TLS session for Anonymous TLS and VeNCrypt */
gnutls_session_t
tlsSession
;
#endif
/* To support security types that requires user input (except VNC password
* authentication), for example VeNCrypt and MSLogon, this callback function
* must be set before the authentication. Otherwise, it implicates that the
* caller application does not support it and related security types should
* be bypassed.
*/
GetCredentialProc
GetCredential
;
}
rfbClient
;
}
rfbClient
;
/* cursor.c */
/* cursor.c */
...
...
rfb/rfbproto.h
View file @
f49a2927
...
@@ -264,6 +264,18 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
...
@@ -264,6 +264,18 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
#define rfbTight 16
#define rfbTight 16
#define rfbUltra 17
#define rfbUltra 17
#define rfbTLS 18
#define rfbTLS 18
#define rfbVeNCrypt 19
#define rfbMSLogon 0xfffffffa
#define rfbVeNCryptPlain 256
#define rfbVeNCryptTLSNone 257
#define rfbVeNCryptTLSVNC 258
#define rfbVeNCryptTLSPlain 259
#define rfbVeNCryptX509None 260
#define rfbVeNCryptX509VNC 261
#define rfbVeNCryptX509Plain 262
#define rfbVeNCryptX509SASL 263
#define rfbVeNCryptTLSSASL 264
/*
/*
* rfbConnFailed: For some reason the connection failed (e.g. the server
* rfbConnFailed: For some reason the connection failed (e.g. the server
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment