1 /* 2 * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <assert.h> 11 #include <openssl/configuration.h> 12 #include <openssl/bio.h> 13 #include "internal/e_os.h" /* For struct timeval */ 14 #include "quictestlib.h" 15 #include "ssltestlib.h" 16 #include "../testutil.h" 17 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 18 #include "../threadstest.h" 19 #endif 20 #include "internal/quic_ssl.h" 21 #include "internal/quic_wire_pkt.h" 22 #include "internal/quic_record_tx.h" 23 #include "internal/quic_error.h" 24 #include "internal/packet.h" 25 #include "internal/tsan_assist.h" 26 27 #define GROWTH_ALLOWANCE 1024 28 29 struct noise_args_data_st { 30 BIO *cbio; 31 BIO *sbio; 32 BIO *tracebio; 33 int flags; 34 }; 35 36 struct qtest_fault { 37 QUIC_TSERVER *qtserv; 38 39 /* Plain packet mutations */ 40 /* Header for the plaintext packet */ 41 QUIC_PKT_HDR pplainhdr; 42 /* iovec for the plaintext packet data buffer */ 43 OSSL_QTX_IOVEC pplainio; 44 /* Allocated size of the plaintext packet data buffer */ 45 size_t pplainbuf_alloc; 46 qtest_fault_on_packet_plain_cb pplaincb; 47 void *pplaincbarg; 48 49 /* Handshake message mutations */ 50 /* Handshake message buffer */ 51 unsigned char *handbuf; 52 /* Allocated size of the handshake message buffer */ 53 size_t handbufalloc; 54 /* Actual length of the handshake message */ 55 size_t handbuflen; 56 qtest_fault_on_handshake_cb handshakecb; 57 void *handshakecbarg; 58 qtest_fault_on_enc_ext_cb encextcb; 59 void *encextcbarg; 60 61 /* Cipher packet mutations */ 62 qtest_fault_on_packet_cipher_cb pciphercb; 63 void *pciphercbarg; 64 65 /* Datagram mutations */ 66 qtest_fault_on_datagram_cb datagramcb; 67 void *datagramcbarg; 68 /* The currently processed message */ 69 BIO_MSG msg; 70 /* Allocated size of msg data buffer */ 71 size_t msgalloc; 72 struct noise_args_data_st noiseargs; 73 }; 74 75 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 76 static int client_ready = 0; 77 static CRYPTO_CONDVAR *client_ready_cond = NULL; 78 static CRYPTO_MUTEX *client_ready_mutex = NULL; 79 #endif 80 81 static void packet_plain_finish(void *arg); 82 static void handshake_finish(void *arg); 83 static OSSL_TIME qtest_get_time(void); 84 static void qtest_reset_time(void); 85 86 static int using_fake_time = 0; 87 static OSSL_TIME fake_now; 88 static CRYPTO_RWLOCK *fake_now_lock = NULL; 89 static OSSL_TIME start_time; 90 91 static OSSL_TIME fake_now_cb(void *arg) 92 { 93 return qtest_get_time(); 94 } 95 96 static void noise_msg_callback(int write_p, int version, int content_type, 97 const void *buf, size_t len, SSL *ssl, 98 void *arg) 99 { 100 struct noise_args_data_st *noiseargs = (struct noise_args_data_st *)arg; 101 102 if (content_type == SSL3_RT_QUIC_FRAME_FULL) { 103 PACKET pkt; 104 uint64_t frame_type; 105 106 if (!PACKET_buf_init(&pkt, buf, len)) 107 return; 108 109 if (!ossl_quic_wire_peek_frame_header(&pkt, &frame_type, NULL)) 110 return; 111 112 if (frame_type == OSSL_QUIC_FRAME_TYPE_PING) { 113 /* 114 * If either endpoint issues a ping frame then we are in danger 115 * of our noise being too much such that the connection itself 116 * fails. We back off on the noise for a bit to avoid that. 117 */ 118 (void)BIO_ctrl(noiseargs->cbio, BIO_CTRL_NOISE_BACK_OFF, 1, NULL); 119 (void)BIO_ctrl(noiseargs->sbio, BIO_CTRL_NOISE_BACK_OFF, 1, NULL); 120 } 121 } 122 123 #ifndef OPENSSL_NO_SSL_TRACE 124 if ((noiseargs->flags & QTEST_FLAG_CLIENT_TRACE) != 0 125 && !SSL_is_server(ssl)) 126 SSL_trace(write_p, version, content_type, buf, len, ssl, 127 noiseargs->tracebio); 128 #endif 129 } 130 131 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, 132 SSL_CTX *serverctx, char *certfile, char *keyfile, 133 int flags, QUIC_TSERVER **qtserv, SSL **cssl, 134 QTEST_FAULT **fault, BIO **tracebio) 135 { 136 /* ALPN value as recognised by QUIC_TSERVER */ 137 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' }; 138 QUIC_TSERVER_ARGS tserver_args = { 0 }; 139 BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL; 140 BIO_ADDR *peeraddr = NULL; 141 struct in_addr ina = { 0 }; 142 BIO *tmpbio = NULL; 143 QTEST_DATA *bdata = NULL; 144 145 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 146 if (client_ready_cond == NULL) { 147 client_ready_cond = ossl_crypto_condvar_new(); 148 if (client_ready_cond == NULL) 149 return 0; 150 } 151 152 if (client_ready_mutex == NULL) { 153 client_ready_mutex = ossl_crypto_mutex_new(); 154 if (client_ready_mutex == NULL) { 155 ossl_crypto_condvar_free(&client_ready_cond); 156 client_ready_cond = NULL; 157 return 0; 158 } 159 } 160 #endif 161 162 bdata = OPENSSL_zalloc(sizeof(QTEST_DATA)); 163 if (bdata == NULL) 164 return 0; 165 166 *qtserv = NULL; 167 168 if (fault != NULL) { 169 *fault = OPENSSL_zalloc(sizeof(**fault)); 170 if (*fault == NULL) 171 goto err; 172 bdata->fault = *fault; 173 } 174 175 if (*cssl == NULL) { 176 *cssl = SSL_new(clientctx); 177 if (!TEST_ptr(*cssl)) 178 goto err; 179 } 180 181 #ifndef OPENSSL_NO_SSL_TRACE 182 if ((flags & QTEST_FLAG_CLIENT_TRACE) != 0) { 183 tmpbio = BIO_new_fp(stdout, BIO_NOCLOSE); 184 if (!TEST_ptr(tmpbio)) 185 goto err; 186 187 SSL_set_msg_callback(*cssl, SSL_trace); 188 SSL_set_msg_callback_arg(*cssl, tmpbio); 189 } 190 #endif 191 if (tracebio != NULL) 192 *tracebio = tmpbio; 193 194 /* SSL_set_alpn_protos returns 0 for success! */ 195 if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn)))) 196 goto err; 197 198 if (!TEST_ptr(peeraddr = BIO_ADDR_new())) 199 goto err; 200 201 if ((flags & QTEST_FLAG_BLOCK) != 0) { 202 #if !defined(OPENSSL_NO_POSIX_IO) 203 int cfd, sfd; 204 205 /* 206 * For blocking mode we need to create actual sockets rather than doing 207 * everything in memory 208 */ 209 if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_DGRAM, peeraddr))) 210 goto err; 211 cbio = BIO_new_dgram(cfd, 1); 212 if (!TEST_ptr(cbio)) { 213 close(cfd); 214 close(sfd); 215 goto err; 216 } 217 sbio = BIO_new_dgram(sfd, 1); 218 if (!TEST_ptr(sbio)) { 219 close(sfd); 220 goto err; 221 } 222 #else 223 goto err; 224 #endif 225 } else { 226 BIO_ADDR *localaddr = NULL; 227 228 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0))) 229 goto err; 230 231 if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) 232 || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))) 233 goto err; 234 235 if (!TEST_ptr(localaddr = BIO_ADDR_new())) 236 goto err; 237 /* Dummy client local addresses */ 238 if (!TEST_true(BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), 239 htons(0)))) { 240 BIO_ADDR_free(localaddr); 241 goto err; 242 } 243 if (!TEST_int_eq(BIO_dgram_set0_local_addr(cbio, localaddr), 1)) { 244 BIO_ADDR_free(localaddr); 245 goto err; 246 } 247 /* Dummy server address */ 248 if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina), 249 htons(0)))) 250 goto err; 251 } 252 253 if ((flags & QTEST_FLAG_PACKET_SPLIT) != 0) { 254 BIO *pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); 255 256 if (!TEST_ptr(pktsplitbio)) 257 goto err; 258 cbio = BIO_push(pktsplitbio, cbio); 259 BIO_set_data(pktsplitbio, bdata); 260 261 pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); 262 if (!TEST_ptr(pktsplitbio)) 263 goto err; 264 sbio = BIO_push(pktsplitbio, sbio); 265 BIO_set_data(pktsplitbio, bdata); 266 } 267 268 if ((flags & QTEST_FLAG_NOISE) != 0) { 269 BIO *noisebio; 270 struct bio_noise_now_cb_st now_cb = { fake_now_cb, NULL }; 271 272 /* 273 * It is an error to not have a QTEST_FAULT object when introducing noise 274 */ 275 if (!TEST_ptr(fault)) 276 goto err; 277 278 noisebio = BIO_new(bio_f_noisy_dgram_filter()); 279 280 if (!TEST_ptr(noisebio)) 281 goto err; 282 cbio = BIO_push(noisebio, cbio); 283 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 284 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SET_NOW_CB, 285 0, &now_cb), 286 1)) 287 goto err; 288 } 289 290 noisebio = BIO_new(bio_f_noisy_dgram_filter()); 291 292 if (!TEST_ptr(noisebio)) 293 goto err; 294 sbio = BIO_push(noisebio, sbio); 295 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 296 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SET_NOW_CB, 297 0, &now_cb), 298 1)) 299 goto err; 300 } 301 302 (void)BIO_ctrl(sbio, BIO_CTRL_NOISE_BACK_OFF, 2, NULL); 303 304 (*fault)->noiseargs.cbio = cbio; 305 (*fault)->noiseargs.sbio = sbio; 306 (*fault)->noiseargs.tracebio = tmpbio; 307 (*fault)->noiseargs.flags = flags; 308 309 SSL_set_msg_callback(*cssl, noise_msg_callback); 310 SSL_set_msg_callback_arg(*cssl, &(*fault)->noiseargs); 311 } 312 313 SSL_set_bio(*cssl, cbio, cbio); 314 315 if (!TEST_true(SSL_set_blocking_mode(*cssl, 316 (flags & QTEST_FLAG_BLOCK) != 0 ? 1 : 0))) 317 goto err; 318 319 if (!TEST_true(SSL_set1_initial_peer_addr(*cssl, peeraddr))) 320 goto err; 321 322 fisbio = BIO_new(qtest_get_bio_method()); 323 if (!TEST_ptr(fisbio)) 324 goto err; 325 326 BIO_set_data(fisbio, bdata); 327 328 if (!BIO_up_ref(sbio)) 329 goto err; 330 if (!TEST_ptr(BIO_push(fisbio, sbio))) { 331 BIO_free(sbio); 332 goto err; 333 } 334 335 tserver_args.libctx = libctx; 336 tserver_args.net_rbio = sbio; 337 tserver_args.net_wbio = fisbio; 338 tserver_args.alpn = NULL; 339 if (serverctx != NULL && !TEST_true(SSL_CTX_up_ref(serverctx))) 340 goto err; 341 tserver_args.ctx = serverctx; 342 if (fake_now_lock == NULL) { 343 fake_now_lock = CRYPTO_THREAD_lock_new(); 344 if (fake_now_lock == NULL) 345 goto err; 346 } 347 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { 348 using_fake_time = 1; 349 qtest_reset_time(); 350 tserver_args.now_cb = fake_now_cb; 351 (void)ossl_quic_set_override_now_cb(*cssl, fake_now_cb, NULL); 352 } else { 353 using_fake_time = 0; 354 } 355 356 if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile, 357 keyfile))) 358 goto err; 359 360 bdata->short_conn_id_len = ossl_quic_tserver_get_short_header_conn_id_len(*qtserv); 361 /* Ownership of fisbio and sbio is now held by *qtserv */ 362 sbio = NULL; 363 fisbio = NULL; 364 365 if ((flags & QTEST_FLAG_NOISE) != 0) 366 ossl_quic_tserver_set_msg_callback(*qtserv, noise_msg_callback, 367 &(*fault)->noiseargs); 368 369 if (fault != NULL) 370 (*fault)->qtserv = *qtserv; 371 372 BIO_ADDR_free(peeraddr); 373 374 return 1; 375 err: 376 SSL_CTX_free(tserver_args.ctx); 377 BIO_ADDR_free(peeraddr); 378 BIO_free_all(cbio); 379 BIO_free_all(fisbio); 380 BIO_free_all(sbio); 381 SSL_free(*cssl); 382 *cssl = NULL; 383 ossl_quic_tserver_free(*qtserv); 384 if (fault != NULL) 385 OPENSSL_free(*fault); 386 OPENSSL_free(bdata); 387 BIO_free(tmpbio); 388 if (tracebio != NULL) 389 *tracebio = NULL; 390 391 return 0; 392 } 393 394 void qtest_add_time(uint64_t millis) 395 { 396 if (!CRYPTO_THREAD_write_lock(fake_now_lock)) 397 return; 398 fake_now = ossl_time_add(fake_now, ossl_ms2time(millis)); 399 CRYPTO_THREAD_unlock(fake_now_lock); 400 } 401 402 static OSSL_TIME qtest_get_time(void) 403 { 404 OSSL_TIME ret; 405 406 if (!CRYPTO_THREAD_read_lock(fake_now_lock)) 407 return ossl_time_zero(); 408 ret = fake_now; 409 CRYPTO_THREAD_unlock(fake_now_lock); 410 return ret; 411 } 412 413 static void qtest_reset_time(void) 414 { 415 if (!CRYPTO_THREAD_write_lock(fake_now_lock)) 416 return; 417 fake_now = ossl_time_zero(); 418 CRYPTO_THREAD_unlock(fake_now_lock); 419 /* zero time can have a special meaning, bump it */ 420 qtest_add_time(1); 421 } 422 423 void qtest_start_stopwatch(void) 424 { 425 start_time = qtest_get_time(); 426 } 427 428 uint64_t qtest_get_stopwatch_time(void) 429 { 430 return ossl_time2ms(ossl_time_subtract(qtest_get_time(), start_time)); 431 } 432 433 QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts) 434 { 435 QTEST_FAULT *f; 436 437 f = OPENSSL_zalloc(sizeof(*f)); 438 if (f == NULL) 439 return NULL; 440 441 f->qtserv = ts; 442 return f; 443 } 444 445 int qtest_supports_blocking(void) 446 { 447 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 448 return 1; 449 #else 450 return 0; 451 #endif 452 } 453 454 #define MAXLOOPS 1000 455 456 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 457 static int globserverret = 0; 458 static TSAN_QUALIFIER int abortserverthread = 0; 459 static QUIC_TSERVER *globtserv; 460 static const thread_t thread_zero; 461 static void run_server_thread(void) 462 { 463 /* 464 * This will operate in a busy loop because the server does not block, 465 * but should be acceptable because it is local and we expect this to be 466 * fast 467 */ 468 globserverret = qtest_create_quic_connection(globtserv, NULL); 469 } 470 #endif 471 472 int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv) 473 { 474 struct timeval tv; 475 OSSL_TIME ctimeout, stimeout, mintimeout, now; 476 int cinf; 477 478 /* We don't need to wait in blocking mode */ 479 if (s == NULL || SSL_get_blocking_mode(s)) 480 return 1; 481 482 /* Don't wait if either BIO has data waiting */ 483 if (BIO_pending(SSL_get_rbio(s)) > 0 484 || BIO_pending(ossl_quic_tserver_get0_rbio(qtserv)) > 0) 485 return 1; 486 487 /* 488 * Neither endpoint has data waiting to be read. We assume data transmission 489 * is instantaneous due to using mem based BIOs, so there is no data "in 490 * flight" and no more data will be sent by either endpoint until some time 491 * based event has occurred. Therefore, wait for a timeout to occur. This 492 * might happen if we are using the noisy BIO and datagrams have been lost. 493 */ 494 if (!SSL_get_event_timeout(s, &tv, &cinf)) 495 return 0; 496 497 if (using_fake_time) 498 now = qtest_get_time(); 499 else 500 now = ossl_time_now(); 501 502 ctimeout = cinf ? ossl_time_infinite() : ossl_time_from_timeval(tv); 503 stimeout = ossl_time_subtract(ossl_quic_tserver_get_deadline(qtserv), now); 504 mintimeout = ossl_time_min(ctimeout, stimeout); 505 if (ossl_time_is_infinite(mintimeout)) 506 return 0; 507 508 if (using_fake_time) 509 qtest_add_time(ossl_time2ms(mintimeout)); 510 else 511 OSSL_sleep(ossl_time2ms(mintimeout)); 512 513 return 1; 514 } 515 516 int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl, 517 int wanterr) 518 { 519 int retc = -1, rets = 0, abortctr = 0, ret = 0; 520 int clienterr = 0, servererr = 0; 521 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 522 523 /* 524 * Pointless initialisation to avoid bogus compiler warnings about using 525 * t uninitialised 526 */ 527 thread_t t = thread_zero; 528 529 if (clientssl != NULL) 530 abortserverthread = 0; 531 532 /* 533 * Only set the client_ready flag to zero if we are the client 534 */ 535 if (clientssl != NULL) { 536 ossl_crypto_mutex_lock(client_ready_mutex); 537 client_ready = 0; 538 ossl_crypto_mutex_unlock(client_ready_mutex); 539 } 540 #endif 541 542 if (!TEST_ptr(qtserv)) { 543 goto err; 544 } else if (clientssl == NULL) { 545 retc = 1; 546 } else if (SSL_get_blocking_mode(clientssl) > 0) { 547 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 548 /* 549 * clientssl is blocking. We will need a thread to complete the 550 * connection 551 */ 552 globtserv = qtserv; 553 if (!TEST_true(run_thread(&t, run_server_thread))) 554 goto err; 555 556 qtserv = NULL; 557 rets = 1; 558 #else 559 TEST_error("No thread support in this build"); 560 goto err; 561 #endif 562 } 563 564 do { 565 if (!clienterr && retc <= 0) { 566 int err; 567 568 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 569 ossl_crypto_mutex_lock(client_ready_mutex); 570 client_ready = 1; 571 ossl_crypto_condvar_broadcast(client_ready_cond); 572 ossl_crypto_mutex_unlock(client_ready_mutex); 573 #endif 574 retc = SSL_connect(clientssl); 575 if (retc <= 0) { 576 err = SSL_get_error(clientssl, retc); 577 578 if (err == wanterr) { 579 retc = 1; 580 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 581 if (qtserv == NULL && rets > 0) 582 tsan_store(&abortserverthread, 1); 583 else 584 #endif 585 rets = 1; 586 } else { 587 if (err != SSL_ERROR_WANT_READ 588 && err != SSL_ERROR_WANT_WRITE) { 589 TEST_info("SSL_connect() failed %d, %d", retc, err); 590 TEST_openssl_errors(); 591 clienterr = 1; 592 } 593 } 594 } 595 } 596 597 qtest_add_time(1); 598 if (clientssl != NULL) 599 SSL_handle_events(clientssl); 600 if (qtserv != NULL) { 601 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 602 ossl_crypto_mutex_lock(client_ready_mutex); 603 for (;;) { 604 if (client_ready == 1) 605 break; 606 ossl_crypto_condvar_wait(client_ready_cond, client_ready_mutex); 607 } 608 ossl_crypto_mutex_unlock(client_ready_mutex); 609 #endif 610 ossl_quic_tserver_tick(qtserv); 611 } 612 613 if (!servererr && rets <= 0) { 614 servererr = ossl_quic_tserver_is_term_any(qtserv); 615 if (!servererr) 616 rets = ossl_quic_tserver_is_handshake_confirmed(qtserv); 617 } 618 619 if (clienterr && servererr) 620 goto err; 621 622 if (clientssl != NULL && ++abortctr == MAXLOOPS) { 623 TEST_info("No progress made"); 624 goto err; 625 } 626 627 if ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr)) { 628 if (!qtest_wait_for_timeout(clientssl, qtserv)) 629 goto err; 630 } 631 } while ((retc <= 0 && !clienterr) 632 || (rets <= 0 && !servererr 633 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 634 && !tsan_load(&abortserverthread) 635 #endif 636 )); 637 638 if (qtserv == NULL && rets > 0) { 639 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 640 /* 641 * Make sure we unblock the server before we wait on completion here 642 * in case it didn't happen in the connect loop above 643 */ 644 ossl_crypto_mutex_lock(client_ready_mutex); 645 client_ready = 1; 646 ossl_crypto_condvar_broadcast(client_ready_cond); 647 ossl_crypto_mutex_unlock(client_ready_mutex); 648 if (!TEST_true(wait_for_thread(t)) || !TEST_true(globserverret)) 649 goto err; 650 #else 651 TEST_error("Should not happen"); 652 goto err; 653 #endif 654 } 655 656 if (!clienterr && !servererr) 657 ret = 1; 658 err: 659 return ret; 660 } 661 662 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl) 663 { 664 return qtest_create_quic_connection_ex(qtserv, clientssl, SSL_ERROR_NONE); 665 } 666 667 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 668 static TSAN_QUALIFIER int shutdowndone; 669 670 static void run_server_shutdown_thread(void) 671 { 672 /* 673 * This will operate in a busy loop because the server does not block, 674 * but should be acceptable because it is local and we expect this to be 675 * fast 676 */ 677 do { 678 ossl_quic_tserver_tick(globtserv); 679 } while (!tsan_load(&shutdowndone)); 680 } 681 #endif 682 683 int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl) 684 { 685 int tickserver = 1; 686 int ret = 0; 687 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 688 /* 689 * Pointless initialisation to avoid bogus compiler warnings about using 690 * t uninitialised 691 */ 692 thread_t t = thread_zero; 693 694 ossl_crypto_condvar_free(&client_ready_cond); 695 client_ready_cond = NULL; 696 ossl_crypto_mutex_free(&client_ready_mutex); 697 client_ready_mutex = NULL; 698 #endif 699 700 if (SSL_get_blocking_mode(clientssl) > 0) { 701 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 702 /* 703 * clientssl is blocking. We will need a thread to complete the 704 * connection 705 */ 706 globtserv = qtserv; 707 shutdowndone = 0; 708 if (!TEST_true(run_thread(&t, run_server_shutdown_thread))) 709 return 0; 710 711 tickserver = 0; 712 #else 713 TEST_error("No thread support in this build"); 714 return 0; 715 #endif 716 } 717 718 /* Busy loop in non-blocking mode. It should be quick because its local */ 719 for (;;) { 720 int rc = SSL_shutdown(clientssl); 721 722 if (rc == 1) { 723 ret = 1; 724 break; 725 } 726 727 if (rc < 0) 728 break; 729 730 if (tickserver) 731 ossl_quic_tserver_tick(qtserv); 732 } 733 734 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 735 tsan_store(&shutdowndone, 1); 736 if (!tickserver) { 737 if (!TEST_true(wait_for_thread(t))) 738 ret = 0; 739 } 740 #endif 741 742 return ret; 743 } 744 745 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code) 746 { 747 const QUIC_TERMINATE_CAUSE *cause; 748 749 ossl_quic_tserver_tick(qtserv); 750 751 /* 752 * Check that the server has closed with the specified code from the client 753 */ 754 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv))) 755 return 0; 756 757 cause = ossl_quic_tserver_get_terminate_cause(qtserv); 758 if (!TEST_ptr(cause) 759 || !TEST_true(cause->remote) 760 || !TEST_false(cause->app) 761 || !TEST_uint64_t_eq(cause->error_code, code)) 762 return 0; 763 764 return 1; 765 } 766 767 int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv) 768 { 769 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_PROTOCOL_VIOLATION); 770 } 771 772 int qtest_check_server_frame_encoding_err(QUIC_TSERVER *qtserv) 773 { 774 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_FRAME_ENCODING_ERROR); 775 } 776 777 void qtest_fault_free(QTEST_FAULT *fault) 778 { 779 if (fault == NULL) 780 return; 781 782 packet_plain_finish(fault); 783 handshake_finish(fault); 784 785 OPENSSL_free(fault); 786 } 787 788 static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin, 789 const OSSL_QTX_IOVEC *iovecin, size_t numin, 790 QUIC_PKT_HDR **hdrout, 791 const OSSL_QTX_IOVEC **iovecout, 792 size_t *numout, 793 void *arg) 794 { 795 QTEST_FAULT *fault = arg; 796 size_t i, bufsz = 0; 797 unsigned char *cur; 798 int grow_allowance; 799 800 /* Coalesce our data into a single buffer */ 801 802 /* First calculate required buffer size */ 803 for (i = 0; i < numin; i++) 804 bufsz += iovecin[i].buf_len; 805 806 fault->pplainio.buf_len = bufsz; 807 808 /* 809 * 1200 is QUIC payload length we use 810 * bufsz is what we got from txp 811 * 16 is the length of tag added by encryption 812 * 14 long header (we assume token length is 0, 813 * which is fine for server not so fine for client) 814 */ 815 grow_allowance = 1200 - bufsz - 16 - 14; 816 grow_allowance -= hdrin->dst_conn_id.id_len; 817 grow_allowance -= hdrin->src_conn_id.id_len; 818 assert(grow_allowance >= 0); 819 bufsz += grow_allowance; 820 821 fault->pplainio.buf = cur = OPENSSL_malloc(bufsz); 822 if (cur == NULL) { 823 fault->pplainio.buf_len = 0; 824 return 0; 825 } 826 827 fault->pplainbuf_alloc = bufsz; 828 829 /* Copy in the data from the input buffers */ 830 for (i = 0; i < numin; i++) { 831 memcpy(cur, iovecin[i].buf, iovecin[i].buf_len); 832 cur += iovecin[i].buf_len; 833 } 834 835 fault->pplainhdr = *hdrin; 836 837 /* 838 * Cast below is safe because we allocated the buffer 839 * mutation is best effort. we can inject frame if 840 * there is enough space. If there is not enough space 841 * we must give up. 842 */ 843 if (fault->pplaincb != NULL) 844 fault->pplaincb(fault, &fault->pplainhdr, 845 (unsigned char *)fault->pplainio.buf, 846 fault->pplainio.buf_len, fault->pplaincbarg); 847 848 *hdrout = &fault->pplainhdr; 849 *iovecout = &fault->pplainio; 850 *numout = 1; 851 852 return 1; 853 } 854 855 static void packet_plain_finish(void *arg) 856 { 857 QTEST_FAULT *fault = arg; 858 859 /* Cast below is safe because we allocated the buffer */ 860 OPENSSL_free((unsigned char *)fault->pplainio.buf); 861 fault->pplainio.buf_len = 0; 862 fault->pplainbuf_alloc = 0; 863 fault->pplainio.buf = NULL; 864 } 865 866 int qtest_fault_set_packet_plain_listener(QTEST_FAULT *fault, 867 qtest_fault_on_packet_plain_cb pplaincb, 868 void *pplaincbarg) 869 { 870 fault->pplaincb = pplaincb; 871 fault->pplaincbarg = pplaincbarg; 872 873 return ossl_quic_tserver_set_plain_packet_mutator(fault->qtserv, 874 packet_plain_mutate, 875 packet_plain_finish, 876 fault); 877 } 878 879 /* To be called from a packet_plain_listener callback */ 880 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen) 881 { 882 unsigned char *buf; 883 size_t oldlen = fault->pplainio.buf_len; 884 885 /* 886 * Alloc'd size should always be non-zero, so if this fails we've been 887 * incorrectly called 888 */ 889 if (fault->pplainbuf_alloc == 0) 890 return 0; 891 892 if (newlen > fault->pplainbuf_alloc) { 893 /* This exceeds our growth allowance. Fail */ 894 return 0; 895 } 896 897 /* Cast below is safe because we allocated the buffer */ 898 buf = (unsigned char *)fault->pplainio.buf; 899 900 if (newlen > oldlen) { 901 /* Extend packet with 0 bytes */ 902 memset(buf + oldlen, 0, newlen - oldlen); 903 } /* else we're truncating or staying the same */ 904 905 fault->pplainio.buf_len = newlen; 906 fault->pplainhdr.len = newlen; 907 908 return 1; 909 } 910 911 /* 912 * Prepend frame data into a packet. To be called from a packet_plain_listener 913 * callback 914 */ 915 int qtest_fault_prepend_frame(QTEST_FAULT *fault, const unsigned char *frame, 916 size_t frame_len) 917 { 918 unsigned char *buf; 919 size_t old_len; 920 921 /* 922 * Alloc'd size should always be non-zero, so if this fails we've been 923 * incorrectly called 924 */ 925 if (fault->pplainbuf_alloc == 0) 926 return 0; 927 928 /* Cast below is safe because we allocated the buffer */ 929 buf = (unsigned char *)fault->pplainio.buf; 930 old_len = fault->pplainio.buf_len; 931 932 /* Extend the size of the packet by the size of the new frame */ 933 if (!TEST_true(qtest_fault_resize_plain_packet(fault, 934 old_len + frame_len))) 935 return 0; 936 937 memmove(buf + frame_len, buf, old_len); 938 memcpy(buf, frame, frame_len); 939 940 return 1; 941 } 942 943 static int handshake_mutate(const unsigned char *msgin, size_t msginlen, 944 unsigned char **msgout, size_t *msgoutlen, 945 void *arg) 946 { 947 QTEST_FAULT *fault = arg; 948 unsigned char *buf; 949 unsigned long payloadlen; 950 unsigned int msgtype; 951 PACKET pkt; 952 953 buf = OPENSSL_malloc(msginlen + GROWTH_ALLOWANCE); 954 if (buf == NULL) 955 return 0; 956 957 fault->handbuf = buf; 958 fault->handbuflen = msginlen; 959 fault->handbufalloc = msginlen + GROWTH_ALLOWANCE; 960 memcpy(buf, msgin, msginlen); 961 962 if (!PACKET_buf_init(&pkt, buf, msginlen) 963 || !PACKET_get_1(&pkt, &msgtype) 964 || !PACKET_get_net_3(&pkt, &payloadlen) 965 || PACKET_remaining(&pkt) != payloadlen) 966 return 0; 967 968 /* Parse specific message types */ 969 switch (msgtype) { 970 case SSL3_MT_ENCRYPTED_EXTENSIONS: { 971 QTEST_ENCRYPTED_EXTENSIONS ee; 972 973 if (fault->encextcb == NULL) 974 break; 975 976 /* 977 * The EncryptedExtensions message is very simple. It just has an 978 * extensions block in it and nothing else. 979 */ 980 ee.extensions = (unsigned char *)PACKET_data(&pkt); 981 ee.extensionslen = payloadlen; 982 if (!fault->encextcb(fault, &ee, payloadlen, fault->encextcbarg)) 983 return 0; 984 } 985 986 default: 987 /* No specific handlers for these message types yet */ 988 break; 989 } 990 991 if (fault->handshakecb != NULL 992 && !fault->handshakecb(fault, buf, fault->handbuflen, 993 fault->handshakecbarg)) 994 return 0; 995 996 *msgout = buf; 997 *msgoutlen = fault->handbuflen; 998 999 return 1; 1000 } 1001 1002 static void handshake_finish(void *arg) 1003 { 1004 QTEST_FAULT *fault = arg; 1005 1006 OPENSSL_free(fault->handbuf); 1007 fault->handbuf = NULL; 1008 } 1009 1010 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault, 1011 qtest_fault_on_handshake_cb handshakecb, 1012 void *handshakecbarg) 1013 { 1014 fault->handshakecb = handshakecb; 1015 fault->handshakecbarg = handshakecbarg; 1016 1017 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, 1018 handshake_mutate, 1019 handshake_finish, 1020 fault); 1021 } 1022 1023 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault, 1024 qtest_fault_on_enc_ext_cb encextcb, 1025 void *encextcbarg) 1026 { 1027 fault->encextcb = encextcb; 1028 fault->encextcbarg = encextcbarg; 1029 1030 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, 1031 handshake_mutate, 1032 handshake_finish, 1033 fault); 1034 } 1035 1036 /* To be called from a handshake_listener callback */ 1037 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen) 1038 { 1039 unsigned char *buf; 1040 size_t oldlen = fault->handbuflen; 1041 1042 /* 1043 * Alloc'd size should always be non-zero, so if this fails we've been 1044 * incorrectly called 1045 */ 1046 if (fault->handbufalloc == 0) 1047 return 0; 1048 1049 if (newlen > fault->handbufalloc) { 1050 /* This exceeds our growth allowance. Fail */ 1051 return 0; 1052 } 1053 1054 buf = (unsigned char *)fault->handbuf; 1055 1056 if (newlen > oldlen) { 1057 /* Extend packet with 0 bytes */ 1058 memset(buf + oldlen, 0, newlen - oldlen); 1059 } /* else we're truncating or staying the same */ 1060 1061 fault->handbuflen = newlen; 1062 return 1; 1063 } 1064 1065 /* To be called from message specific listener callbacks */ 1066 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen) 1067 { 1068 /* First resize the underlying message */ 1069 if (!qtest_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH)) 1070 return 0; 1071 1072 /* Fixup the handshake message header */ 1073 fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff); 1074 fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff); 1075 fault->handbuf[3] = (unsigned char)((newlen) & 0xff); 1076 1077 return 1; 1078 } 1079 1080 int qtest_fault_delete_extension(QTEST_FAULT *fault, 1081 unsigned int exttype, unsigned char *ext, 1082 size_t *extlen, 1083 BUF_MEM *old_ext) 1084 { 1085 PACKET pkt, sub, subext; 1086 WPACKET old_ext_wpkt; 1087 unsigned int type; 1088 const unsigned char *start, *end; 1089 size_t newlen, w; 1090 size_t msglen = fault->handbuflen; 1091 1092 if (!PACKET_buf_init(&pkt, ext, *extlen)) 1093 return 0; 1094 1095 /* Extension block starts with 2 bytes for extension block length */ 1096 if (!PACKET_as_length_prefixed_2(&pkt, &sub)) 1097 return 0; 1098 1099 do { 1100 start = PACKET_data(&sub); 1101 if (!PACKET_get_net_2(&sub, &type) 1102 || !PACKET_get_length_prefixed_2(&sub, &subext)) 1103 return 0; 1104 } while (type != exttype); 1105 1106 /* Found it */ 1107 end = PACKET_data(&sub); 1108 1109 if (old_ext != NULL) { 1110 if (!WPACKET_init(&old_ext_wpkt, old_ext)) 1111 return 0; 1112 1113 if (!WPACKET_memcpy(&old_ext_wpkt, PACKET_data(&subext), 1114 PACKET_remaining(&subext)) 1115 || !WPACKET_get_total_written(&old_ext_wpkt, &w)) { 1116 WPACKET_cleanup(&old_ext_wpkt); 1117 return 0; 1118 } 1119 1120 WPACKET_finish(&old_ext_wpkt); 1121 old_ext->length = w; 1122 } 1123 1124 /* 1125 * If we're not the last extension we need to move the rest earlier. The 1126 * cast below is safe because we own the underlying buffer and we're no 1127 * longer making PACKET calls. 1128 */ 1129 if (end < ext + *extlen) 1130 memmove((unsigned char *)start, end, end - start); 1131 1132 /* 1133 * Calculate new extensions payload length = 1134 * Original length 1135 * - 2 extension block length bytes 1136 * - length of removed extension 1137 */ 1138 newlen = *extlen - 2 - (end - start); 1139 1140 /* Fixup the length bytes for the extension block */ 1141 ext[0] = (unsigned char)((newlen >> 8) & 0xff); 1142 ext[1] = (unsigned char)((newlen) & 0xff); 1143 1144 /* 1145 * Length of the whole extension block is the new payload length plus the 1146 * 2 bytes for the length 1147 */ 1148 *extlen = newlen + 2; 1149 1150 /* We can now resize the message */ 1151 if ((size_t)(end - start) + SSL3_HM_HEADER_LENGTH > msglen) 1152 return 0; /* Should not happen */ 1153 msglen -= (end - start) + SSL3_HM_HEADER_LENGTH; 1154 if (!qtest_fault_resize_message(fault, msglen)) 1155 return 0; 1156 1157 return 1; 1158 } 1159 1160 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER) 1161 1162 static BIO_METHOD *pcipherbiometh = NULL; 1163 1164 #define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n) * (stride))) 1165 1166 static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride, 1167 size_t num_msg, uint64_t flags, 1168 size_t *num_processed) 1169 { 1170 BIO *next = BIO_next(b); 1171 ossl_ssize_t ret = 0; 1172 size_t i = 0, tmpnump; 1173 QUIC_PKT_HDR hdr; 1174 PACKET pkt; 1175 unsigned char *tmpdata; 1176 QTEST_DATA *bdata = NULL; 1177 1178 if (next == NULL) 1179 return 0; 1180 1181 bdata = BIO_get_data(b); 1182 if (bdata == NULL || bdata->fault == NULL 1183 || (bdata->fault->pciphercb == NULL && bdata->fault->datagramcb == NULL)) 1184 return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed); 1185 1186 if (num_msg == 0) { 1187 *num_processed = 0; 1188 return 1; 1189 } 1190 1191 for (i = 0; i < num_msg; ++i) { 1192 bdata->fault->msg = BIO_MSG_N(msg, stride, i); 1193 1194 /* Take a copy of the data so that callbacks can modify it */ 1195 tmpdata = OPENSSL_malloc(bdata->fault->msg.data_len + GROWTH_ALLOWANCE); 1196 if (tmpdata == NULL) 1197 return 0; 1198 memcpy(tmpdata, bdata->fault->msg.data, bdata->fault->msg.data_len); 1199 bdata->fault->msg.data = tmpdata; 1200 bdata->fault->msgalloc = bdata->fault->msg.data_len + GROWTH_ALLOWANCE; 1201 1202 if (bdata->fault->pciphercb != NULL) { 1203 if (!PACKET_buf_init(&pkt, bdata->fault->msg.data, bdata->fault->msg.data_len)) 1204 return 0; 1205 1206 do { 1207 if (!ossl_quic_wire_decode_pkt_hdr(&pkt, 1208 bdata->short_conn_id_len, 1209 1, 0, &hdr, NULL, NULL)) 1210 goto out; 1211 1212 /* 1213 * hdr.data is const - but its our buffer so casting away the 1214 * const is safe 1215 */ 1216 if (!bdata->fault->pciphercb(bdata->fault, &hdr, 1217 (unsigned char *)hdr.data, hdr.len, 1218 bdata->fault->pciphercbarg)) 1219 goto out; 1220 1221 /* 1222 * At the moment modifications to hdr by the callback 1223 * are ignored. We might need to rewrite the QUIC header to 1224 * enable tests to change this. We also don't yet have a 1225 * mechanism for the callback to change the encrypted data 1226 * length. It's not clear if that's needed or not. 1227 */ 1228 } while (PACKET_remaining(&pkt) > 0); 1229 } 1230 1231 if (bdata->fault->datagramcb != NULL 1232 && !bdata->fault->datagramcb(bdata->fault, &bdata->fault->msg, stride, 1233 bdata->fault->datagramcbarg)) 1234 goto out; 1235 1236 if (!BIO_sendmmsg(next, &bdata->fault->msg, stride, 1, flags, &tmpnump)) { 1237 *num_processed = i; 1238 goto out; 1239 } 1240 1241 OPENSSL_free(bdata->fault->msg.data); 1242 bdata->fault->msg.data = NULL; 1243 bdata->fault->msgalloc = 0; 1244 } 1245 1246 *num_processed = i; 1247 out: 1248 ret = i > 0; 1249 OPENSSL_free(bdata->fault->msg.data); 1250 bdata->fault->msg.data = NULL; 1251 return ret; 1252 } 1253 1254 static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg) 1255 { 1256 BIO *next = BIO_next(b); 1257 1258 if (next == NULL) 1259 return -1; 1260 1261 return BIO_ctrl(next, cmd, larg, parg); 1262 } 1263 1264 static int pcipher_destroy(BIO *b) 1265 { 1266 OPENSSL_free(BIO_get_data(b)); 1267 return 1; 1268 } 1269 1270 BIO_METHOD *qtest_get_bio_method(void) 1271 { 1272 BIO_METHOD *tmp; 1273 1274 if (pcipherbiometh != NULL) 1275 return pcipherbiometh; 1276 1277 tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter"); 1278 1279 if (!TEST_ptr(tmp)) 1280 return NULL; 1281 1282 if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg)) 1283 || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl)) 1284 || !TEST_true(BIO_meth_set_destroy(tmp, pcipher_destroy))) 1285 goto err; 1286 1287 pcipherbiometh = tmp; 1288 tmp = NULL; 1289 err: 1290 BIO_meth_free(tmp); 1291 return pcipherbiometh; 1292 } 1293 1294 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault, 1295 qtest_fault_on_packet_cipher_cb pciphercb, 1296 void *pciphercbarg) 1297 { 1298 fault->pciphercb = pciphercb; 1299 fault->pciphercbarg = pciphercbarg; 1300 1301 return 1; 1302 } 1303 1304 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, 1305 qtest_fault_on_datagram_cb datagramcb, 1306 void *datagramcbarg) 1307 { 1308 fault->datagramcb = datagramcb; 1309 fault->datagramcbarg = datagramcbarg; 1310 1311 return 1; 1312 } 1313 1314 /* To be called from a datagram_listener callback */ 1315 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen) 1316 { 1317 if (newlen > fault->msgalloc) 1318 return 0; 1319 1320 if (newlen > fault->msg.data_len) 1321 memset((unsigned char *)fault->msg.data + fault->msg.data_len, 0, 1322 newlen - fault->msg.data_len); 1323 1324 fault->msg.data_len = newlen; 1325 1326 return 1; 1327 } 1328 1329 int qtest_fault_set_bw_limit(QTEST_FAULT *fault, 1330 size_t ctos_bw, size_t stoc_bw, 1331 int noise_rate) 1332 { 1333 BIO *sbio = fault->noiseargs.sbio; 1334 BIO *cbio = fault->noiseargs.cbio; 1335 1336 if (!TEST_ptr(sbio) || !TEST_ptr(cbio)) 1337 return 0; 1338 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) 1339 return 0; 1340 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) 1341 return 0; 1342 /* We set the bandwidth limit on the sending side */ 1343 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, 1344 (long)ctos_bw, NULL), 1345 1)) 1346 return 0; 1347 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, 1348 (long)stoc_bw, NULL), 1349 1)) 1350 return 0; 1351 return 1; 1352 } 1353 1354 int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) 1355 { 1356 /* 1357 * Note it is assumed that the originally allocated data sizes for dst and 1358 * src are the same 1359 */ 1360 memcpy(dst->data, src->data, src->data_len); 1361 dst->data_len = src->data_len; 1362 dst->flags = src->flags; 1363 if (dst->local != NULL) { 1364 if (src->local != NULL) { 1365 if (!TEST_true(BIO_ADDR_copy(dst->local, src->local))) 1366 return 0; 1367 } else { 1368 BIO_ADDR_clear(dst->local); 1369 } 1370 } 1371 if (!TEST_true(BIO_ADDR_copy(dst->peer, src->peer))) 1372 return 0; 1373 1374 return 1; 1375 } 1376