2011-03-30 12:46:40 +00:00
|
|
|
#include "vnc.h"
|
|
|
|
#include <libsec.h>
|
|
|
|
#include <auth.h>
|
|
|
|
|
|
|
|
char *serveraddr;
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
VerLen = 12
|
|
|
|
};
|
|
|
|
|
2020-09-27 16:43:43 +00:00
|
|
|
static char version33[VerLen+1] = "RFB 003.003\n";
|
|
|
|
static char version38[VerLen+1] = "RFB 003.008\n";
|
|
|
|
static int srvversion;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
vncsrvhandshake(Vnc *v)
|
|
|
|
{
|
|
|
|
char msg[VerLen+1];
|
|
|
|
|
2020-09-27 16:43:43 +00:00
|
|
|
strecpy(msg, msg+sizeof msg, version33);
|
2011-03-30 12:46:40 +00:00
|
|
|
if(verbose)
|
2015-01-06 04:02:01 +00:00
|
|
|
fprint(2, "server version: %s\n", msg);
|
2011-03-30 12:46:40 +00:00
|
|
|
vncwrbytes(v, msg, VerLen);
|
|
|
|
vncflush(v);
|
|
|
|
|
|
|
|
vncrdbytes(v, msg, VerLen);
|
|
|
|
if(verbose)
|
2015-01-06 04:02:01 +00:00
|
|
|
fprint(2, "client version: %s\n", msg);
|
2011-03-30 12:46:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
vnchandshake(Vnc *v)
|
|
|
|
{
|
|
|
|
char msg[VerLen+1];
|
|
|
|
|
|
|
|
msg[VerLen] = 0;
|
|
|
|
vncrdbytes(v, msg, VerLen);
|
2020-09-27 16:43:43 +00:00
|
|
|
if(strncmp(msg, "RFB 003.", 8) != 0 ||
|
|
|
|
strncmp(msg, "RFB 003.007\n", VerLen) == 0){
|
2011-03-30 12:46:40 +00:00
|
|
|
werrstr("bad rfb version \"%s\"", msg);
|
|
|
|
return -1;
|
|
|
|
}
|
2020-09-27 16:43:43 +00:00
|
|
|
if(strncmp(msg, "RFB 003.008\n", VerLen) == 0)
|
|
|
|
srvversion = 38;
|
|
|
|
else
|
|
|
|
srvversion = 33;
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
if(verbose)
|
2015-01-06 04:02:01 +00:00
|
|
|
fprint(2, "server version: %s\n", msg);
|
2020-09-27 16:43:43 +00:00
|
|
|
strcpy(msg, version38);
|
2011-03-30 12:46:40 +00:00
|
|
|
vncwrbytes(v, msg, VerLen);
|
|
|
|
vncflush(v);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-27 16:43:43 +00:00
|
|
|
ulong
|
|
|
|
sectype38(Vnc *v)
|
|
|
|
{
|
|
|
|
ulong auth, type;
|
|
|
|
int i, ntypes;
|
|
|
|
|
|
|
|
ntypes = vncrdchar(v);
|
|
|
|
if(ntypes == 0){
|
|
|
|
werrstr("no security types from server");
|
|
|
|
return AFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* choose the "most secure" security type */
|
|
|
|
auth = AFailed;
|
|
|
|
for(i = 0; i < ntypes; i++){
|
|
|
|
type = vncrdchar(v);
|
|
|
|
if(verbose){
|
|
|
|
fprint(2, "auth type %s\n",
|
|
|
|
type == AFailed ? "Invalid" :
|
|
|
|
type == ANoAuth ? "None" :
|
|
|
|
type == AVncAuth ? "VNC" : "Unknown");
|
|
|
|
}
|
|
|
|
if(type > auth)
|
|
|
|
auth = type;
|
|
|
|
}
|
|
|
|
return auth;
|
|
|
|
}
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
int
|
|
|
|
vncauth(Vnc *v, char *keypattern)
|
|
|
|
{
|
2016-12-11 15:52:38 +00:00
|
|
|
char *reason;
|
2011-03-30 12:46:40 +00:00
|
|
|
uchar chal[VncChalLen];
|
|
|
|
ulong auth;
|
|
|
|
|
|
|
|
if(keypattern == nil)
|
|
|
|
keypattern = "";
|
2020-09-27 16:43:43 +00:00
|
|
|
|
|
|
|
auth = srvversion == 38 ? sectype38(v) : vncrdlong(v);
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
switch(auth){
|
|
|
|
default:
|
|
|
|
werrstr("unknown auth type 0x%lux", auth);
|
|
|
|
if(verbose)
|
2015-01-06 04:02:01 +00:00
|
|
|
fprint(2, "unknown auth type 0x%lux\n", auth);
|
2011-03-30 12:46:40 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
case AFailed:
|
2020-09-27 16:43:43 +00:00
|
|
|
failed:
|
2011-03-30 12:46:40 +00:00
|
|
|
reason = vncrdstring(v);
|
|
|
|
werrstr("%s", reason);
|
|
|
|
if(verbose)
|
|
|
|
fprint(2, "auth failed: %s\n", reason);
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case ANoAuth:
|
2020-09-27 16:43:43 +00:00
|
|
|
if(srvversion == 38){
|
|
|
|
vncwrchar(v, auth);
|
|
|
|
vncflush(v);
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
if(verbose)
|
2015-01-06 04:02:01 +00:00
|
|
|
fprint(2, "no auth needed\n");
|
2011-03-30 12:46:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AVncAuth:
|
2020-09-27 16:43:43 +00:00
|
|
|
if(srvversion == 38){
|
|
|
|
vncwrchar(v, auth);
|
|
|
|
vncflush(v);
|
|
|
|
}
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
vncrdbytes(v, chal, VncChalLen);
|
|
|
|
if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey,
|
2018-08-16 18:34:46 +00:00
|
|
|
"proto=vnc role=client server=%s %s", serveraddr, keypattern) != VncChalLen){
|
2016-12-11 15:52:38 +00:00
|
|
|
return -1;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
vncwrbytes(v, chal, VncChalLen);
|
|
|
|
vncflush(v);
|
2020-09-27 16:43:43 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2020-09-27 16:43:43 +00:00
|
|
|
/* in version 3.8 the auth status is always sent, in 3.3 only in AVncAuth */
|
|
|
|
if(srvversion == 38 || auth == AVncAuth){
|
|
|
|
auth = vncrdlong(v); /* auth status */
|
2011-03-30 12:46:40 +00:00
|
|
|
switch(auth){
|
|
|
|
default:
|
|
|
|
werrstr("unknown server response 0x%lux", auth);
|
|
|
|
return -1;
|
|
|
|
case VncAuthFailed:
|
2020-09-27 16:43:43 +00:00
|
|
|
if (srvversion == 38)
|
|
|
|
goto failed;
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
werrstr("server says authentication failed");
|
|
|
|
return -1;
|
|
|
|
case VncAuthTooMany:
|
|
|
|
werrstr("server says too many tries");
|
|
|
|
return -1;
|
|
|
|
case VncAuthOK:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
vncsrvauth(Vnc *v)
|
|
|
|
{
|
|
|
|
Chalstate *c;
|
|
|
|
AuthInfo *ai;
|
|
|
|
|
|
|
|
if((c = auth_challenge("proto=vnc role=server user=%q", getuser()))==nil)
|
|
|
|
sysfatal("vncchal: %r");
|
|
|
|
if(c->nchal != VncChalLen)
|
|
|
|
sysfatal("vncchal got %d bytes wanted %d", c->nchal, VncChalLen);
|
|
|
|
vncwrlong(v, AVncAuth);
|
|
|
|
vncwrbytes(v, c->chal, VncChalLen);
|
|
|
|
vncflush(v);
|
|
|
|
|
|
|
|
vncrdbytes(v, c->chal, VncChalLen);
|
|
|
|
c->resp = c->chal;
|
|
|
|
c->nresp = VncChalLen;
|
|
|
|
ai = auth_response(c);
|
|
|
|
auth_freechal(c);
|
|
|
|
if(ai == nil){
|
|
|
|
fprint(2, "vnc auth failed: server factotum: %r\n");
|
|
|
|
vncwrlong(v, VncAuthFailed);
|
|
|
|
vncflush(v);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
auth_freeAI(ai);
|
|
|
|
vncwrlong(v, VncAuthOK);
|
|
|
|
vncflush(v);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|