vnc: I don't like your face.

Cosmetic improvements to vnc auth code.
Should not have user-visible changes.
This commit is contained in:
Ori Bernstein 2021-01-23 13:20:09 -08:00
parent f321298c55
commit bd5af0df5d
3 changed files with 54 additions and 75 deletions

View file

@ -2,26 +2,12 @@
#include <libsec.h> #include <libsec.h>
#include <auth.h> #include <auth.h>
char *serveraddr;
enum
{
VerLen = 12
};
static char version33[VerLen+1] = "RFB 003.003\n";
static char version38[VerLen+1] = "RFB 003.008\n";
static int srvversion;
int int
vncsrvhandshake(Vnc *v) vncsrvhandshake(Vnc *v)
{ {
char msg[VerLen+1]; char msg[VerLen+1];
strecpy(msg, msg+sizeof msg, version33); vncwrbytes(v, "RFB 003.003\n", VerLen);
if(verbose)
fprint(2, "server version: %s\n", msg);
vncwrbytes(v, msg, VerLen);
vncflush(v); vncflush(v);
vncrdbytes(v, msg, VerLen); vncrdbytes(v, msg, VerLen);
@ -33,67 +19,57 @@ vncsrvhandshake(Vnc *v)
int int
vnchandshake(Vnc *v) vnchandshake(Vnc *v)
{ {
char msg[VerLen+1]; char msg[VerLen + 1];
msg[VerLen] = 0; msg[VerLen] = 0;
vncrdbytes(v, msg, VerLen); vncrdbytes(v, msg, VerLen);
if(strncmp(msg, "RFB 003.", 8) != 0 ||
strncmp(msg, "RFB 003.007\n", VerLen) == 0){
werrstr("bad rfb version \"%s\"", msg);
return -1;
}
if(strncmp(msg, "RFB 003.008\n", VerLen) == 0)
srvversion = 38;
else
srvversion = 33;
if(verbose) if(verbose)
fprint(2, "server version: %s\n", msg); fprint(2, "server version: %s\n", msg);
strcpy(msg, version38);
if(strncmp(msg, "RFB 003.003\n", VerLen) == 0)
v->vers = 33;
else if(strncmp(msg, "RFB 003.007\n", VerLen) == 0)
v->vers = 37;
else if(strncmp(msg, "RFB 003.008\n", VerLen) == 0)
v->vers = 38;
else /* RFC6143: Any other should be treated as 3.3. */
v->vers = 33;
strcpy(msg, "RFB 003.008\n");
vncwrbytes(v, msg, VerLen); vncwrbytes(v, msg, VerLen);
vncflush(v); vncflush(v);
return 0; return 0;
} }
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 && type <= AVncAuth)
auth = type;
}
return auth;
}
int int
vncauth(Vnc *v, char *keypattern) vncauth(Vnc *v, char *keypattern)
{ {
char *reason;
uchar chal[VncChalLen]; uchar chal[VncChalLen];
ulong auth; ulong auth, type;
int i, ntypes;
char *err;
if(keypattern == nil) if(keypattern == nil)
keypattern = ""; keypattern = "";
auth = srvversion == 38 ? sectype38(v) : vncrdlong(v); auth = AFailed;
if(v->vers == 33)
auth = vncrdlong(v);
else{
ntypes = vncrdchar(v);
for(i = 0; i < ntypes; i++){
type = vncrdchar(v);
if(verbose)
fprint(2, "auth type %uld\n", type);
if(type > auth && type <= AVncAuth)
auth = type;
}
if(auth == AFailed){
werrstr("no supported auth types");
return -1;
}
}
switch(auth){ switch(auth){
default: default:
@ -103,15 +79,14 @@ vncauth(Vnc *v, char *keypattern)
return -1; return -1;
case AFailed: case AFailed:
failed: err = vncrdstring(v);
reason = vncrdstring(v); werrstr("%s", err);
werrstr("%s", reason);
if(verbose) if(verbose)
fprint(2, "auth failed: %s\n", reason); fprint(2, "auth failed: %s\n", err);
return -1; return -1;
case ANoAuth: case ANoAuth:
if(srvversion == 38){ if(v->vers == 38){
vncwrchar(v, auth); vncwrchar(v, auth);
vncflush(v); vncflush(v);
} }
@ -120,14 +95,14 @@ vncauth(Vnc *v, char *keypattern)
break; break;
case AVncAuth: case AVncAuth:
if(srvversion == 38){ if(v->vers == 38){
vncwrchar(v, auth); vncwrchar(v, auth);
vncflush(v); vncflush(v);
} }
vncrdbytes(v, chal, VncChalLen); vncrdbytes(v, chal, VncChalLen);
if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey, if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey,
"proto=vnc role=client server=%s %s", serveraddr, keypattern) != VncChalLen){ "proto=vnc role=client server=%s %s", v->srvaddr, keypattern) != VncChalLen){
return -1; return -1;
} }
vncwrbytes(v, chal, VncChalLen); vncwrbytes(v, chal, VncChalLen);
@ -135,18 +110,18 @@ vncauth(Vnc *v, char *keypattern)
break; break;
} }
/* in version 3.8 the auth status is always sent, in 3.3 only in AVncAuth */ /* in version 3.8 the auth status is always sent, in 3.3 and 3.7, only in AVncAuth */
if(srvversion == 38 || auth == AVncAuth){ if(v->vers == 38 || auth == AVncAuth){
auth = vncrdlong(v); /* auth status */ auth = vncrdlong(v); /* auth status */
switch(auth){ switch(auth){
default: default:
werrstr("unknown server response 0x%lux", auth); werrstr("unknown server response 0x%lux", auth);
return -1; return -1;
case VncAuthFailed: case VncAuthFailed:
if (srvversion == 38) err = (v->vers == 38) ? vncrdstring(v) : "rejected";
goto failed; werrstr("%s", err);
if(verbose)
werrstr("server says authentication failed"); fprint(2, "auth failed: %s\n", err);
return -1; return -1;
case VncAuthTooMany: case VncAuthTooMany:
werrstr("server says too many tries"); werrstr("server says too many tries");

View file

@ -33,7 +33,11 @@ struct Vnc {
Rectangle dim; Rectangle dim;
Pixfmt; Pixfmt;
char *name; /* client only */
/* client only */
char *name;
char *srvaddr;
int vers;
int canresize; int canresize;
struct { struct {
@ -44,6 +48,7 @@ struct Vnc {
}; };
enum { enum {
VerLen = 12,
/* authentication negotiation */ /* authentication negotiation */
AFailed = 0, AFailed = 0,
ANoAuth, ANoAuth,
@ -142,4 +147,3 @@ extern void hexdump(void*, int);
extern void vnchungup(Vnc*); extern void vnchungup(Vnc*);
extern int verbose; extern int verbose;
extern char* serveraddr;

View file

@ -111,10 +111,9 @@ main(int argc, char **argv)
if(argc != 1) if(argc != 1)
usage(); usage();
serveraddr = strdup(argv[0]); dfd = dial(netmkvncaddr(argv[0]), nil, nil, &cfd);
dfd = dial(netmkvncaddr(serveraddr), nil, nil, &cfd);
if(dfd < 0) if(dfd < 0)
sysfatal("cannot dial %s: %r", serveraddr); sysfatal("cannot dial %s: %r", argv[0]);
if(tls){ if(tls){
TLSconn conn; TLSconn conn;
@ -126,6 +125,7 @@ main(int argc, char **argv)
free(conn.sessionID); free(conn.sessionID);
} }
vnc = vncinit(dfd, cfd, nil); vnc = vncinit(dfd, cfd, nil);
vnc->srvaddr = strdup(argv[0]);
if(vnchandshake(vnc) < 0) if(vnchandshake(vnc) < 0)
sysfatal("handshake failure: %r"); sysfatal("handshake failure: %r");