1 #include "vnc.h" 2 #include <libsec.h> 3 #include <auth.h> 4 5 char *serveraddr; 6 7 /* 8 * Encrypt n bytes using the password 9 * as key, padded with zeros to 8 bytes. 10 */ 11 enum 12 { 13 VerLen = 12 14 }; 15 16 static char version[VerLen+1] = "RFB 003.003\n"; 17 18 static uchar tab[256]; 19 20 /* VNC reverses the bits of each byte before using as a des key */ 21 static void 22 mktab(void) 23 { 24 int i, j, k; 25 static int once; 26 27 if(once) 28 return; 29 once = 1; 30 31 for(i=0; i<256; i++) { 32 j=i; 33 tab[i] = 0; 34 for(k=0; k<8; k++) { 35 tab[i] = (tab[i]<<1) | (j&1); 36 j >>= 1; 37 } 38 } 39 } 40 41 static void 42 vncencrypt(uchar *buf, int n, char *pw) 43 { 44 uchar *p; 45 uchar key[9]; 46 DESstate s; 47 48 mktab(); 49 memset(key, 0, sizeof key); 50 strncpy((char*)key, pw, 8); 51 for(p=key; *p; p++) 52 *p = tab[*p]; 53 54 setupDESstate(&s, key, nil); 55 desECBencrypt(buf, n, &s); 56 } 57 58 static int 59 readln(char *prompt, char *line, int len) 60 { 61 char *p; 62 int fd, ctl, n, nr; 63 64 fd = open("/dev/cons", ORDWR); 65 if(fd < 0) 66 sysfatal("couldn't open cons"); 67 ctl = open("/dev/consctl", OWRITE); 68 if(ctl < 0) 69 sysfatal("couldn't open consctl"); 70 write(ctl, "rawon", 5); 71 fprint(fd, "%s", prompt); 72 nr = 0; 73 p = line; 74 for(;;){ 75 n = read(fd, p, 1); 76 if(n < 0){ 77 close(fd); 78 close(ctl); 79 return -1; 80 } 81 if(n == 0 || *p == '\n' || *p == '\r'){ 82 *p = '\0'; 83 write(fd, "\n", 1); 84 close(fd); 85 close(ctl); 86 return nr; 87 } 88 if(*p == '\b'){ 89 if(nr > 0){ 90 nr--; 91 p--; 92 } 93 }else if(*p == 21){ /* cntrl-u */ 94 fprint(fd, "\n%s", prompt); 95 nr = 0; 96 p = line; 97 }else{ 98 nr++; 99 p++; 100 } 101 if(nr == len){ 102 fprint(fd, "line too long; try again\n%s", prompt); 103 nr = 0; 104 p = line; 105 } 106 } 107 return -1; 108 } 109 110 int 111 vnchandshake_srv(Vnc *v) 112 { 113 char msg[VerLen+1]; 114 115 strcpy(msg, version); 116 if(v->extended) 117 msg[0] = 'E'; 118 if(verbose) 119 fprint(2, "server version: %s\n", msg); 120 vncwrbytes(v, msg, VerLen); 121 vncflush(v); 122 123 vncrdbytes(v, msg, VerLen); 124 if(verbose) 125 fprint(2, "client version: %s", msg); 126 return 0; 127 } 128 129 int 130 vnchandshake(Vnc *v) 131 { 132 char msg[VerLen+1]; 133 134 vncrdbytes(v, msg, VerLen); 135 if(strncmp(msg, "RFB ", 4) == 0) 136 v->extended = 0; 137 else if(strncmp(msg, "EFB ", 4) == 0) 138 v->extended = 1; 139 else{ 140 werrstr("bad rfb version \"%s\"", msg); 141 return -1; 142 } 143 if(verbose) 144 fprint(2, "server version %s\n", msg); 145 strcpy(msg, version); 146 if(v->extended) 147 msg[0] = 'E'; 148 vncwrbytes(v, msg, VerLen); 149 vncflush(v); 150 return 0; 151 } 152 153 int 154 vncauth(Vnc *v) 155 { 156 char pw[128], *reason; 157 uchar chal[VncChalLen]; 158 ulong auth; 159 160 auth = vncrdlong(v); 161 switch(auth) { 162 default: 163 werrstr("unknown auth type 0x%lux", auth); 164 if(verbose) 165 fprint(2, "unknown auth type 0x%lux", auth); 166 return -1; 167 168 case AFailed: 169 reason = vncrdstring(v); 170 werrstr("%s", reason); 171 if(verbose) 172 fprint(2, "auth failed: %s\n", reason); 173 return -1; 174 175 case ANoAuth: 176 if(verbose) 177 fprint(2, "no auth needed"); 178 break; 179 180 case AVncAuth: 181 vncrdbytes(v, chal, VncChalLen); 182 183 if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey, 184 "proto=vnc role=client server=%s", serveraddr) != VncChalLen){ 185 /* BUG: rip this out once people have new kernels */ 186 readln("password: ", pw, sizeof(pw)); 187 vncencrypt(chal, VncChalLen, pw); 188 memset(pw, 0, sizeof pw); 189 } 190 vncwrbytes(v, chal, VncChalLen); 191 vncflush(v); 192 193 auth = vncrdlong(v); 194 switch(auth) { 195 default: 196 werrstr("unknown auth response 0x%lux", auth); 197 return -1; 198 case VncAuthFailed: 199 werrstr("authentication failed"); 200 return -1; 201 case VncAuthTooMany: 202 werrstr("authentication failed - too many tries"); 203 return -1; 204 case VncAuthOK: 205 break; 206 } 207 break; 208 } 209 return 0; 210 } 211 212 int 213 vncauth_srv(Vnc *v) 214 { 215 Chalstate *c; 216 struct AuthInfo * ai; 217 218 if((c = auth_challenge("proto=vnc role=server user=%q", getuser()))==nil || c->nchal != VncChalLen) 219 sysfatal("vncchal returned with error\n"); 220 vncwrlong(v, AVncAuth); 221 vncwrbytes(v, c->chal, VncChalLen); 222 vncflush(v); 223 224 vncrdbytes(v, c->chal, VncChalLen); 225 c->resp = c->chal; 226 c->nresp = VncChalLen; 227 ai = auth_response(c); 228 auth_freechal(c); 229 if(ai == nil){ 230 if(verbose) 231 fprint(2, "VNC auth failed\n"); 232 return -1; 233 } 234 auth_freeAI(ai); 235 vncwrlong(v, VncAuthOK); 236 vncflush(v); 237 238 return 0; 239 } 240 241