1 /* 2 * QEMU VNC display driver: SASL auth protocol 3 * 4 * Copyright (C) 2009 Red Hat, Inc 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "vnc.h" 27 28 /* Max amount of data we send/recv for SASL steps to prevent DOS */ 29 #define SASL_DATA_MAX_LEN (1024 * 1024) 30 31 32 void vnc_sasl_client_cleanup(VncState *vs) 33 { 34 if (vs->sasl.conn) { 35 vs->sasl.runSSF = false; 36 vs->sasl.wantSSF = false; 37 vs->sasl.waitWriteSSF = 0; 38 vs->sasl.encodedLength = vs->sasl.encodedOffset = 0; 39 vs->sasl.encoded = NULL; 40 g_free(vs->sasl.username); 41 g_free(vs->sasl.mechlist); 42 vs->sasl.username = vs->sasl.mechlist = NULL; 43 sasl_dispose(&vs->sasl.conn); 44 vs->sasl.conn = NULL; 45 } 46 } 47 48 49 long vnc_client_write_sasl(VncState *vs) 50 { 51 long ret; 52 53 VNC_DEBUG("Write SASL: Pending output %p size %zd offset %zd " 54 "Encoded: %p size %d offset %d\n", 55 vs->output.buffer, vs->output.capacity, vs->output.offset, 56 vs->sasl.encoded, vs->sasl.encodedLength, vs->sasl.encodedOffset); 57 58 if (!vs->sasl.encoded) { 59 int err; 60 err = sasl_encode(vs->sasl.conn, 61 (char *)vs->output.buffer, 62 vs->output.offset, 63 (const char **)&vs->sasl.encoded, 64 &vs->sasl.encodedLength); 65 if (err != SASL_OK) 66 return vnc_client_io_error(vs, -1, NULL); 67 68 vs->sasl.encodedOffset = 0; 69 } 70 71 ret = vnc_client_write_buf(vs, 72 vs->sasl.encoded + vs->sasl.encodedOffset, 73 vs->sasl.encodedLength - vs->sasl.encodedOffset); 74 if (!ret) 75 return 0; 76 77 vs->sasl.encodedOffset += ret; 78 if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { 79 vs->output.offset = 0; 80 vs->sasl.encoded = NULL; 81 vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; 82 } 83 84 /* Can't merge this block with one above, because 85 * someone might have written more unencrypted 86 * data in vs->output while we were processing 87 * SASL encoded output 88 */ 89 if (vs->output.offset == 0) { 90 if (vs->ioc_tag) { 91 g_source_remove(vs->ioc_tag); 92 } 93 vs->ioc_tag = qio_channel_add_watch( 94 vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); 95 } 96 97 return ret; 98 } 99 100 101 long vnc_client_read_sasl(VncState *vs) 102 { 103 long ret; 104 uint8_t encoded[4096]; 105 const char *decoded; 106 unsigned int decodedLen; 107 int err; 108 109 ret = vnc_client_read_buf(vs, encoded, sizeof(encoded)); 110 if (!ret) 111 return 0; 112 113 err = sasl_decode(vs->sasl.conn, 114 (char *)encoded, ret, 115 &decoded, &decodedLen); 116 117 if (err != SASL_OK) 118 return vnc_client_io_error(vs, -1, NULL); 119 VNC_DEBUG("Read SASL Encoded %p size %ld Decoded %p size %d\n", 120 encoded, ret, decoded, decodedLen); 121 buffer_reserve(&vs->input, decodedLen); 122 buffer_append(&vs->input, decoded, decodedLen); 123 return decodedLen; 124 } 125 126 127 static int vnc_auth_sasl_check_access(VncState *vs) 128 { 129 const void *val; 130 int err; 131 int allow; 132 133 err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val); 134 if (err != SASL_OK) { 135 VNC_DEBUG("cannot query SASL username on connection %d (%s), denying access\n", 136 err, sasl_errstring(err, NULL, NULL)); 137 return -1; 138 } 139 if (val == NULL) { 140 VNC_DEBUG("no client username was found, denying access\n"); 141 return -1; 142 } 143 VNC_DEBUG("SASL client username %s\n", (const char *)val); 144 145 vs->sasl.username = g_strdup((const char*)val); 146 147 if (vs->vd->sasl.acl == NULL) { 148 VNC_DEBUG("no ACL activated, allowing access\n"); 149 return 0; 150 } 151 152 allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username); 153 154 VNC_DEBUG("SASL client %s %s by ACL\n", vs->sasl.username, 155 allow ? "allowed" : "denied"); 156 return allow ? 0 : -1; 157 } 158 159 static int vnc_auth_sasl_check_ssf(VncState *vs) 160 { 161 const void *val; 162 int err, ssf; 163 164 if (!vs->sasl.wantSSF) 165 return 1; 166 167 err = sasl_getprop(vs->sasl.conn, SASL_SSF, &val); 168 if (err != SASL_OK) 169 return 0; 170 171 ssf = *(const int *)val; 172 VNC_DEBUG("negotiated an SSF of %d\n", ssf); 173 if (ssf < 56) 174 return 0; /* 56 is good for Kerberos */ 175 176 /* Only setup for read initially, because we're about to send an RPC 177 * reply which must be in plain text. When the next incoming RPC 178 * arrives, we'll switch on writes too 179 * 180 * cf qemudClientReadSASL in qemud.c 181 */ 182 vs->sasl.runSSF = 1; 183 184 /* We have a SSF that's good enough */ 185 return 1; 186 } 187 188 /* 189 * Step Msg 190 * 191 * Input from client: 192 * 193 * u32 clientin-length 194 * u8-array clientin-string 195 * 196 * Output to client: 197 * 198 * u32 serverout-length 199 * u8-array serverout-strin 200 * u8 continue 201 */ 202 203 static int protocol_client_auth_sasl_step_len(VncState *vs, uint8_t *data, size_t len); 204 205 static int protocol_client_auth_sasl_step(VncState *vs, uint8_t *data, size_t len) 206 { 207 uint32_t datalen = len; 208 const char *serverout; 209 unsigned int serveroutlen; 210 int err; 211 char *clientdata = NULL; 212 213 /* NB, distinction of NULL vs "" is *critical* in SASL */ 214 if (datalen) { 215 clientdata = (char*)data; 216 clientdata[datalen-1] = '\0'; /* Wire includes '\0', but make sure */ 217 datalen--; /* Don't count NULL byte when passing to _start() */ 218 } 219 220 VNC_DEBUG("Step using SASL Data %p (%d bytes)\n", 221 clientdata, datalen); 222 err = sasl_server_step(vs->sasl.conn, 223 clientdata, 224 datalen, 225 &serverout, 226 &serveroutlen); 227 if (err != SASL_OK && 228 err != SASL_CONTINUE) { 229 VNC_DEBUG("sasl step failed %d (%s)\n", 230 err, sasl_errdetail(vs->sasl.conn)); 231 sasl_dispose(&vs->sasl.conn); 232 vs->sasl.conn = NULL; 233 goto authabort; 234 } 235 236 if (serveroutlen > SASL_DATA_MAX_LEN) { 237 VNC_DEBUG("sasl step reply data too long %d\n", 238 serveroutlen); 239 sasl_dispose(&vs->sasl.conn); 240 vs->sasl.conn = NULL; 241 goto authabort; 242 } 243 244 VNC_DEBUG("SASL return data %d bytes, nil; %d\n", 245 serveroutlen, serverout ? 0 : 1); 246 247 if (serveroutlen) { 248 vnc_write_u32(vs, serveroutlen + 1); 249 vnc_write(vs, serverout, serveroutlen + 1); 250 } else { 251 vnc_write_u32(vs, 0); 252 } 253 254 /* Whether auth is complete */ 255 vnc_write_u8(vs, err == SASL_CONTINUE ? 0 : 1); 256 257 if (err == SASL_CONTINUE) { 258 VNC_DEBUG("%s", "Authentication must continue\n"); 259 /* Wait for step length */ 260 vnc_read_when(vs, protocol_client_auth_sasl_step_len, 4); 261 } else { 262 if (!vnc_auth_sasl_check_ssf(vs)) { 263 VNC_DEBUG("Authentication rejected for weak SSF %p\n", vs->ioc); 264 goto authreject; 265 } 266 267 /* Check username whitelist ACL */ 268 if (vnc_auth_sasl_check_access(vs) < 0) { 269 VNC_DEBUG("Authentication rejected for ACL %p\n", vs->ioc); 270 goto authreject; 271 } 272 273 VNC_DEBUG("Authentication successful %p\n", vs->ioc); 274 vnc_write_u32(vs, 0); /* Accept auth */ 275 /* 276 * Delay writing in SSF encoded mode until pending output 277 * buffer is written 278 */ 279 if (vs->sasl.runSSF) 280 vs->sasl.waitWriteSSF = vs->output.offset; 281 start_client_init(vs); 282 } 283 284 return 0; 285 286 authreject: 287 vnc_write_u32(vs, 1); /* Reject auth */ 288 vnc_write_u32(vs, sizeof("Authentication failed")); 289 vnc_write(vs, "Authentication failed", sizeof("Authentication failed")); 290 vnc_flush(vs); 291 vnc_client_error(vs); 292 return -1; 293 294 authabort: 295 vnc_client_error(vs); 296 return -1; 297 } 298 299 static int protocol_client_auth_sasl_step_len(VncState *vs, uint8_t *data, size_t len) 300 { 301 uint32_t steplen = read_u32(data, 0); 302 VNC_DEBUG("Got client step len %d\n", steplen); 303 if (steplen > SASL_DATA_MAX_LEN) { 304 VNC_DEBUG("Too much SASL data %d\n", steplen); 305 vnc_client_error(vs); 306 return -1; 307 } 308 309 if (steplen == 0) 310 return protocol_client_auth_sasl_step(vs, NULL, 0); 311 else 312 vnc_read_when(vs, protocol_client_auth_sasl_step, steplen); 313 return 0; 314 } 315 316 /* 317 * Start Msg 318 * 319 * Input from client: 320 * 321 * u32 clientin-length 322 * u8-array clientin-string 323 * 324 * Output to client: 325 * 326 * u32 serverout-length 327 * u8-array serverout-strin 328 * u8 continue 329 */ 330 331 #define SASL_DATA_MAX_LEN (1024 * 1024) 332 333 static int protocol_client_auth_sasl_start(VncState *vs, uint8_t *data, size_t len) 334 { 335 uint32_t datalen = len; 336 const char *serverout; 337 unsigned int serveroutlen; 338 int err; 339 char *clientdata = NULL; 340 341 /* NB, distinction of NULL vs "" is *critical* in SASL */ 342 if (datalen) { 343 clientdata = (char*)data; 344 clientdata[datalen-1] = '\0'; /* Should be on wire, but make sure */ 345 datalen--; /* Don't count NULL byte when passing to _start() */ 346 } 347 348 VNC_DEBUG("Start SASL auth with mechanism %s. Data %p (%d bytes)\n", 349 vs->sasl.mechlist, clientdata, datalen); 350 err = sasl_server_start(vs->sasl.conn, 351 vs->sasl.mechlist, 352 clientdata, 353 datalen, 354 &serverout, 355 &serveroutlen); 356 if (err != SASL_OK && 357 err != SASL_CONTINUE) { 358 VNC_DEBUG("sasl start failed %d (%s)\n", 359 err, sasl_errdetail(vs->sasl.conn)); 360 sasl_dispose(&vs->sasl.conn); 361 vs->sasl.conn = NULL; 362 goto authabort; 363 } 364 if (serveroutlen > SASL_DATA_MAX_LEN) { 365 VNC_DEBUG("sasl start reply data too long %d\n", 366 serveroutlen); 367 sasl_dispose(&vs->sasl.conn); 368 vs->sasl.conn = NULL; 369 goto authabort; 370 } 371 372 VNC_DEBUG("SASL return data %d bytes, nil; %d\n", 373 serveroutlen, serverout ? 0 : 1); 374 375 if (serveroutlen) { 376 vnc_write_u32(vs, serveroutlen + 1); 377 vnc_write(vs, serverout, serveroutlen + 1); 378 } else { 379 vnc_write_u32(vs, 0); 380 } 381 382 /* Whether auth is complete */ 383 vnc_write_u8(vs, err == SASL_CONTINUE ? 0 : 1); 384 385 if (err == SASL_CONTINUE) { 386 VNC_DEBUG("%s", "Authentication must continue\n"); 387 /* Wait for step length */ 388 vnc_read_when(vs, protocol_client_auth_sasl_step_len, 4); 389 } else { 390 if (!vnc_auth_sasl_check_ssf(vs)) { 391 VNC_DEBUG("Authentication rejected for weak SSF %p\n", vs->ioc); 392 goto authreject; 393 } 394 395 /* Check username whitelist ACL */ 396 if (vnc_auth_sasl_check_access(vs) < 0) { 397 VNC_DEBUG("Authentication rejected for ACL %p\n", vs->ioc); 398 goto authreject; 399 } 400 401 VNC_DEBUG("Authentication successful %p\n", vs->ioc); 402 vnc_write_u32(vs, 0); /* Accept auth */ 403 start_client_init(vs); 404 } 405 406 return 0; 407 408 authreject: 409 vnc_write_u32(vs, 1); /* Reject auth */ 410 vnc_write_u32(vs, sizeof("Authentication failed")); 411 vnc_write(vs, "Authentication failed", sizeof("Authentication failed")); 412 vnc_flush(vs); 413 vnc_client_error(vs); 414 return -1; 415 416 authabort: 417 vnc_client_error(vs); 418 return -1; 419 } 420 421 static int protocol_client_auth_sasl_start_len(VncState *vs, uint8_t *data, size_t len) 422 { 423 uint32_t startlen = read_u32(data, 0); 424 VNC_DEBUG("Got client start len %d\n", startlen); 425 if (startlen > SASL_DATA_MAX_LEN) { 426 VNC_DEBUG("Too much SASL data %d\n", startlen); 427 vnc_client_error(vs); 428 return -1; 429 } 430 431 if (startlen == 0) 432 return protocol_client_auth_sasl_start(vs, NULL, 0); 433 434 vnc_read_when(vs, protocol_client_auth_sasl_start, startlen); 435 return 0; 436 } 437 438 static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_t len) 439 { 440 char *mechname = g_strndup((const char *) data, len); 441 VNC_DEBUG("Got client mechname '%s' check against '%s'\n", 442 mechname, vs->sasl.mechlist); 443 444 if (strncmp(vs->sasl.mechlist, mechname, len) == 0) { 445 if (vs->sasl.mechlist[len] != '\0' && 446 vs->sasl.mechlist[len] != ',') { 447 VNC_DEBUG("One %d", vs->sasl.mechlist[len]); 448 goto fail; 449 } 450 } else { 451 char *offset = strstr(vs->sasl.mechlist, mechname); 452 VNC_DEBUG("Two %p\n", offset); 453 if (!offset) { 454 goto fail; 455 } 456 VNC_DEBUG("Two '%s'\n", offset); 457 if (offset[-1] != ',' || 458 (offset[len] != '\0'&& 459 offset[len] != ',')) { 460 goto fail; 461 } 462 } 463 464 g_free(vs->sasl.mechlist); 465 vs->sasl.mechlist = mechname; 466 467 VNC_DEBUG("Validated mechname '%s'\n", mechname); 468 vnc_read_when(vs, protocol_client_auth_sasl_start_len, 4); 469 return 0; 470 471 fail: 472 vnc_client_error(vs); 473 g_free(mechname); 474 return -1; 475 } 476 477 static int protocol_client_auth_sasl_mechname_len(VncState *vs, uint8_t *data, size_t len) 478 { 479 uint32_t mechlen = read_u32(data, 0); 480 VNC_DEBUG("Got client mechname len %d\n", mechlen); 481 if (mechlen > 100) { 482 VNC_DEBUG("Too long SASL mechname data %d\n", mechlen); 483 vnc_client_error(vs); 484 return -1; 485 } 486 if (mechlen < 1) { 487 VNC_DEBUG("Too short SASL mechname %d\n", mechlen); 488 vnc_client_error(vs); 489 return -1; 490 } 491 vnc_read_when(vs, protocol_client_auth_sasl_mechname,mechlen); 492 return 0; 493 } 494 495 static char * 496 vnc_socket_ip_addr_string(QIOChannelSocket *ioc, 497 bool local, 498 Error **errp) 499 { 500 SocketAddress *addr; 501 char *ret; 502 503 if (local) { 504 addr = qio_channel_socket_get_local_address(ioc, errp); 505 } else { 506 addr = qio_channel_socket_get_remote_address(ioc, errp); 507 } 508 if (!addr) { 509 return NULL; 510 } 511 512 if (addr->type != SOCKET_ADDRESS_KIND_INET) { 513 error_setg(errp, "Not an inet socket type"); 514 return NULL; 515 } 516 ret = g_strdup_printf("%s;%s", addr->u.inet->host, addr->u.inet->port); 517 qapi_free_SocketAddress(addr); 518 return ret; 519 } 520 521 void start_auth_sasl(VncState *vs) 522 { 523 const char *mechlist = NULL; 524 sasl_security_properties_t secprops; 525 int err; 526 char *localAddr, *remoteAddr; 527 int mechlistlen; 528 529 VNC_DEBUG("Initialize SASL auth %p\n", vs->ioc); 530 531 /* Get local & remote client addresses in form IPADDR;PORT */ 532 localAddr = vnc_socket_ip_addr_string(vs->sioc, true, NULL); 533 if (!localAddr) { 534 goto authabort; 535 } 536 537 remoteAddr = vnc_socket_ip_addr_string(vs->sioc, false, NULL); 538 if (!remoteAddr) { 539 g_free(localAddr); 540 goto authabort; 541 } 542 543 err = sasl_server_new("vnc", 544 NULL, /* FQDN - just delegates to gethostname */ 545 NULL, /* User realm */ 546 localAddr, 547 remoteAddr, 548 NULL, /* Callbacks, not needed */ 549 SASL_SUCCESS_DATA, 550 &vs->sasl.conn); 551 g_free(localAddr); 552 g_free(remoteAddr); 553 localAddr = remoteAddr = NULL; 554 555 if (err != SASL_OK) { 556 VNC_DEBUG("sasl context setup failed %d (%s)", 557 err, sasl_errstring(err, NULL, NULL)); 558 vs->sasl.conn = NULL; 559 goto authabort; 560 } 561 562 /* Inform SASL that we've got an external SSF layer from TLS/x509 */ 563 if (vs->auth == VNC_AUTH_VENCRYPT && 564 vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) { 565 Error *local_err = NULL; 566 int keysize; 567 sasl_ssf_t ssf; 568 569 keysize = qcrypto_tls_session_get_key_size(vs->tls, 570 &local_err); 571 if (keysize < 0) { 572 VNC_DEBUG("cannot TLS get cipher size: %s\n", 573 error_get_pretty(local_err)); 574 error_free(local_err); 575 sasl_dispose(&vs->sasl.conn); 576 vs->sasl.conn = NULL; 577 goto authabort; 578 } 579 ssf = keysize * CHAR_BIT; /* tls key size is bytes, sasl wants bits */ 580 581 err = sasl_setprop(vs->sasl.conn, SASL_SSF_EXTERNAL, &ssf); 582 if (err != SASL_OK) { 583 VNC_DEBUG("cannot set SASL external SSF %d (%s)\n", 584 err, sasl_errstring(err, NULL, NULL)); 585 sasl_dispose(&vs->sasl.conn); 586 vs->sasl.conn = NULL; 587 goto authabort; 588 } 589 } else { 590 vs->sasl.wantSSF = 1; 591 } 592 593 memset (&secprops, 0, sizeof secprops); 594 /* Inform SASL that we've got an external SSF layer from TLS. 595 * 596 * Disable SSF, if using TLS+x509+SASL only. TLS without x509 597 * is not sufficiently strong 598 */ 599 if (vs->vd->is_unix || 600 (vs->auth == VNC_AUTH_VENCRYPT && 601 vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)) { 602 /* If we've got TLS or UNIX domain sock, we don't care about SSF */ 603 secprops.min_ssf = 0; 604 secprops.max_ssf = 0; 605 secprops.maxbufsize = 8192; 606 secprops.security_flags = 0; 607 } else { 608 /* Plain TCP, better get an SSF layer */ 609 secprops.min_ssf = 56; /* Good enough to require kerberos */ 610 secprops.max_ssf = 100000; /* Arbitrary big number */ 611 secprops.maxbufsize = 8192; 612 /* Forbid any anonymous or trivially crackable auth */ 613 secprops.security_flags = 614 SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; 615 } 616 617 err = sasl_setprop(vs->sasl.conn, SASL_SEC_PROPS, &secprops); 618 if (err != SASL_OK) { 619 VNC_DEBUG("cannot set SASL security props %d (%s)\n", 620 err, sasl_errstring(err, NULL, NULL)); 621 sasl_dispose(&vs->sasl.conn); 622 vs->sasl.conn = NULL; 623 goto authabort; 624 } 625 626 err = sasl_listmech(vs->sasl.conn, 627 NULL, /* Don't need to set user */ 628 "", /* Prefix */ 629 ",", /* Separator */ 630 "", /* Suffix */ 631 &mechlist, 632 NULL, 633 NULL); 634 if (err != SASL_OK) { 635 VNC_DEBUG("cannot list SASL mechanisms %d (%s)\n", 636 err, sasl_errdetail(vs->sasl.conn)); 637 sasl_dispose(&vs->sasl.conn); 638 vs->sasl.conn = NULL; 639 goto authabort; 640 } 641 VNC_DEBUG("Available mechanisms for client: '%s'\n", mechlist); 642 643 vs->sasl.mechlist = g_strdup(mechlist); 644 mechlistlen = strlen(mechlist); 645 vnc_write_u32(vs, mechlistlen); 646 vnc_write(vs, mechlist, mechlistlen); 647 vnc_flush(vs); 648 649 VNC_DEBUG("Wait for client mechname length\n"); 650 vnc_read_when(vs, protocol_client_auth_sasl_mechname_len, 4); 651 652 return; 653 654 authabort: 655 vnc_client_error(vs); 656 } 657 658 659