1267188Sjkim/* test/heartbeat_test.c */ 2280304Sjkim/*- 3267188Sjkim * Unit test for TLS heartbeats. 4267188Sjkim * 5267188Sjkim * Acts as a regression test against the Heartbleed bug (CVE-2014-0160). 6267188Sjkim * 7267188Sjkim * Author: Mike Bland (mbland@acm.org, http://mike-bland.com/) 8267188Sjkim * Date: 2014-04-12 9267188Sjkim * License: Creative Commons Attribution 4.0 International (CC By 4.0) 10267188Sjkim * http://creativecommons.org/licenses/by/4.0/deed.en_US 11267188Sjkim * 12267188Sjkim * OUTPUT 13267188Sjkim * ------ 14267188Sjkim * The program returns zero on success. It will print a message with a count 15267188Sjkim * of the number of failed tests and return nonzero if any tests fail. 16267188Sjkim * 17267188Sjkim * It will print the contents of the request and response buffers for each 18267188Sjkim * failing test. In a "fixed" version, all the tests should pass and there 19267188Sjkim * should be no output. 20267188Sjkim * 21267188Sjkim * In a "bleeding" version, you'll see: 22267188Sjkim * 23267188Sjkim * test_dtls1_heartbleed failed: 24267188Sjkim * expected payload len: 0 25267188Sjkim * received: 1024 26267188Sjkim * sent 26 characters 27267188Sjkim * "HEARTBLEED " 28267188Sjkim * received 1024 characters 29267188Sjkim * "HEARTBLEED \xde\xad\xbe\xef..." 30267188Sjkim * ** test_dtls1_heartbleed failed ** 31267188Sjkim * 32267188Sjkim * The contents of the returned buffer in the failing test will depend on the 33267188Sjkim * contents of memory on your machine. 34267188Sjkim * 35267188Sjkim * MORE INFORMATION 36267188Sjkim * ---------------- 37267188Sjkim * http://mike-bland.com/2014/04/12/heartbleed.html 38267188Sjkim * http://mike-bland.com/tags/heartbleed.html 39267188Sjkim */ 40267188Sjkim 41269686Sjkim#define OPENSSL_UNIT_TEST 42269686Sjkim 43269686Sjkim#include "../test/testutil.h" 44269686Sjkim 45267188Sjkim#include "../ssl/ssl_locl.h" 46267188Sjkim#include <ctype.h> 47267188Sjkim#include <stdio.h> 48267188Sjkim#include <stdlib.h> 49267188Sjkim#include <string.h> 50267188Sjkim 51269686Sjkim#if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST) 52267188Sjkim 53267188Sjkim/* As per https://tools.ietf.org/html/rfc6520#section-4 */ 54280304Sjkim# define MIN_PADDING_SIZE 16 55267188Sjkim 56267188Sjkim/* Maximum number of payload characters to print as test output */ 57280304Sjkim# define MAX_PRINTABLE_CHARACTERS 1024 58267188Sjkim 59280304Sjkimtypedef struct heartbeat_test_fixture { 60280304Sjkim SSL_CTX *ctx; 61280304Sjkim SSL *s; 62280304Sjkim const char *test_case_name; 63280304Sjkim int (*process_heartbeat) (SSL *s); 64280304Sjkim unsigned char *payload; 65280304Sjkim int sent_payload_len; 66280304Sjkim int expected_return_value; 67280304Sjkim int return_payload_offset; 68280304Sjkim int expected_payload_len; 69280304Sjkim const char *expected_return_payload; 70280304Sjkim} HEARTBEAT_TEST_FIXTURE; 71267188Sjkim 72280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name, 73280304Sjkim const SSL_METHOD *meth) 74280304Sjkim{ 75280304Sjkim HEARTBEAT_TEST_FIXTURE fixture; 76280304Sjkim int setup_ok = 1; 77280304Sjkim memset(&fixture, 0, sizeof(fixture)); 78280304Sjkim fixture.test_case_name = test_case_name; 79267188Sjkim 80280304Sjkim fixture.ctx = SSL_CTX_new(meth); 81280304Sjkim if (!fixture.ctx) { 82280304Sjkim fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n", 83280304Sjkim test_case_name); 84280304Sjkim setup_ok = 0; 85280304Sjkim goto fail; 86280304Sjkim } 87267188Sjkim 88280304Sjkim fixture.s = SSL_new(fixture.ctx); 89280304Sjkim if (!fixture.s) { 90280304Sjkim fprintf(stderr, "Failed to allocate SSL for test: %s\n", 91280304Sjkim test_case_name); 92280304Sjkim setup_ok = 0; 93280304Sjkim goto fail; 94280304Sjkim } 95267188Sjkim 96280304Sjkim if (!ssl_init_wbio_buffer(fixture.s, 1)) { 97280304Sjkim fprintf(stderr, "Failed to set up wbio buffer for test: %s\n", 98280304Sjkim test_case_name); 99280304Sjkim setup_ok = 0; 100280304Sjkim goto fail; 101280304Sjkim } 102267188Sjkim 103280304Sjkim if (!ssl3_setup_buffers(fixture.s)) { 104280304Sjkim fprintf(stderr, "Failed to setup buffers for test: %s\n", 105280304Sjkim test_case_name); 106280304Sjkim setup_ok = 0; 107280304Sjkim goto fail; 108280304Sjkim } 109267188Sjkim 110280304Sjkim /* 111280304Sjkim * Clear the memory for the return buffer, since this isn't automatically 112280304Sjkim * zeroed in opt mode and will cause spurious test failures that will 113280304Sjkim * change with each execution. 114280304Sjkim */ 115280304Sjkim memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len); 116267188Sjkim 117280304Sjkim fail: 118280304Sjkim if (!setup_ok) { 119280304Sjkim ERR_print_errors_fp(stderr); 120280304Sjkim exit(EXIT_FAILURE); 121280304Sjkim } 122280304Sjkim return fixture; 123280304Sjkim} 124267188Sjkim 125280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name) 126280304Sjkim{ 127280304Sjkim HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name, 128280304Sjkim DTLSv1_server_method()); 129280304Sjkim fixture.process_heartbeat = dtls1_process_heartbeat; 130267188Sjkim 131280304Sjkim /* 132280304Sjkim * As per dtls1_get_record(), skipping the following from the beginning 133280304Sjkim * of the returned heartbeat message: type-1 byte; version-2 bytes; 134280304Sjkim * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte 135280304Sjkim * type encoded by process_heartbeat for a total of 14 bytes, at which 136280304Sjkim * point we can grab the length and the payload we seek. 137280304Sjkim */ 138280304Sjkim fixture.return_payload_offset = 14; 139280304Sjkim return fixture; 140280304Sjkim} 141267188Sjkim 142267188Sjkim/* Needed by ssl3_write_bytes() */ 143280304Sjkimstatic int dummy_handshake(SSL *s) 144280304Sjkim{ 145280304Sjkim return 1; 146280304Sjkim} 147267188Sjkim 148280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up_tls(const char *const test_case_name) 149280304Sjkim{ 150280304Sjkim HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name, 151280304Sjkim TLSv1_server_method()); 152280304Sjkim fixture.process_heartbeat = tls1_process_heartbeat; 153280304Sjkim fixture.s->handshake_func = dummy_handshake; 154267188Sjkim 155280304Sjkim /* 156280304Sjkim * As per do_ssl3_write(), skipping the following from the beginning of 157280304Sjkim * the returned heartbeat message: type-1 byte; version-2 bytes; length-2 158280304Sjkim * bytes And then skipping the 1-byte type encoded by process_heartbeat 159280304Sjkim * for a total of 6 bytes, at which point we can grab the length and the 160280304Sjkim * payload we seek. 161280304Sjkim */ 162280304Sjkim fixture.return_payload_offset = 6; 163280304Sjkim return fixture; 164280304Sjkim} 165267188Sjkim 166267188Sjkimstatic void tear_down(HEARTBEAT_TEST_FIXTURE fixture) 167280304Sjkim{ 168280304Sjkim ERR_print_errors_fp(stderr); 169280304Sjkim SSL_free(fixture.s); 170280304Sjkim SSL_CTX_free(fixture.ctx); 171280304Sjkim} 172267188Sjkim 173280304Sjkimstatic void print_payload(const char *const prefix, 174280304Sjkim const unsigned char *payload, const int n) 175280304Sjkim{ 176280304Sjkim const int end = n < MAX_PRINTABLE_CHARACTERS ? n 177280304Sjkim : MAX_PRINTABLE_CHARACTERS; 178280304Sjkim int i = 0; 179267188Sjkim 180280304Sjkim printf("%s %d character%s", prefix, n, n == 1 ? "" : "s"); 181280304Sjkim if (end != n) 182280304Sjkim printf(" (first %d shown)", end); 183280304Sjkim printf("\n \""); 184267188Sjkim 185280304Sjkim for (; i != end; ++i) { 186280304Sjkim const unsigned char c = payload[i]; 187280304Sjkim if (isprint(c)) 188280304Sjkim fputc(c, stdout); 189280304Sjkim else 190280304Sjkim printf("\\x%02x", c); 191280304Sjkim } 192280304Sjkim printf("\"\n"); 193280304Sjkim} 194267188Sjkim 195267188Sjkimstatic int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) 196280304Sjkim{ 197280304Sjkim int result = 0; 198280304Sjkim SSL *s = fixture.s; 199280304Sjkim unsigned char *payload = fixture.payload; 200280304Sjkim unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1]; 201280304Sjkim int return_value; 202280304Sjkim unsigned const char *p; 203280304Sjkim int actual_payload_len; 204267188Sjkim 205280304Sjkim s->s3->rrec.data = payload; 206280304Sjkim s->s3->rrec.length = strlen((const char *)payload); 207280304Sjkim *payload++ = TLS1_HB_REQUEST; 208280304Sjkim s2n(fixture.sent_payload_len, payload); 209267188Sjkim 210280304Sjkim /* 211280304Sjkim * Make a local copy of the request, since it gets overwritten at some 212280304Sjkim * point 213280304Sjkim */ 214280304Sjkim memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf)); 215267188Sjkim 216280304Sjkim return_value = fixture.process_heartbeat(s); 217267188Sjkim 218280304Sjkim if (return_value != fixture.expected_return_value) { 219280304Sjkim printf("%s failed: expected return value %d, received %d\n", 220280304Sjkim fixture.test_case_name, fixture.expected_return_value, 221280304Sjkim return_value); 222280304Sjkim result = 1; 223280304Sjkim } 224267188Sjkim 225280304Sjkim /* 226280304Sjkim * If there is any byte alignment, it will be stored in wbuf.offset. 227280304Sjkim */ 228280304Sjkim p = &(s->s3-> 229280304Sjkim wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]); 230280304Sjkim actual_payload_len = 0; 231280304Sjkim n2s(p, actual_payload_len); 232267188Sjkim 233280304Sjkim if (actual_payload_len != fixture.expected_payload_len) { 234280304Sjkim printf("%s failed:\n expected payload len: %d\n received: %d\n", 235280304Sjkim fixture.test_case_name, fixture.expected_payload_len, 236280304Sjkim actual_payload_len); 237280304Sjkim print_payload("sent", sent_buf, strlen((const char *)sent_buf)); 238280304Sjkim print_payload("received", p, actual_payload_len); 239280304Sjkim result = 1; 240280304Sjkim } else { 241280304Sjkim char *actual_payload = 242280304Sjkim BUF_strndup((const char *)p, actual_payload_len); 243280304Sjkim if (strcmp(actual_payload, fixture.expected_return_payload) != 0) { 244280304Sjkim printf 245280304Sjkim ("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n", 246280304Sjkim fixture.test_case_name, fixture.expected_return_payload, 247280304Sjkim actual_payload); 248280304Sjkim result = 1; 249280304Sjkim } 250280304Sjkim OPENSSL_free(actual_payload); 251280304Sjkim } 252267188Sjkim 253280304Sjkim if (result != 0) { 254280304Sjkim printf("** %s failed **\n--------\n", fixture.test_case_name); 255280304Sjkim } 256280304Sjkim return result; 257280304Sjkim} 258267188Sjkim 259267188Sjkimstatic int honest_payload_size(unsigned char payload_buf[]) 260280304Sjkim{ 261280304Sjkim /* Omit three-byte pad at the beginning for type and payload length */ 262280304Sjkim return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE; 263280304Sjkim} 264267188Sjkim 265280304Sjkim# define SETUP_HEARTBEAT_TEST_FIXTURE(type)\ 266269686Sjkim SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type) 267267188Sjkim 268280304Sjkim# define EXECUTE_HEARTBEAT_TEST()\ 269269686Sjkim EXECUTE_TEST(execute_heartbeat, tear_down) 270267188Sjkim 271267188Sjkimstatic int test_dtls1_not_bleeding() 272280304Sjkim{ 273280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(dtls); 274280304Sjkim /* Three-byte pad at the beginning for type and payload length */ 275280304Sjkim unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" 276280304Sjkim " "; 277280304Sjkim const int payload_buf_len = honest_payload_size(payload_buf); 278267188Sjkim 279280304Sjkim fixture.payload = &payload_buf[0]; 280280304Sjkim fixture.sent_payload_len = payload_buf_len; 281280304Sjkim fixture.expected_return_value = 0; 282280304Sjkim fixture.expected_payload_len = payload_buf_len; 283280304Sjkim fixture.expected_return_payload = 284280304Sjkim "Not bleeding, sixteen spaces of padding"; 285280304Sjkim EXECUTE_HEARTBEAT_TEST(); 286280304Sjkim} 287267188Sjkim 288267188Sjkimstatic int test_dtls1_not_bleeding_empty_payload() 289280304Sjkim{ 290280304Sjkim int payload_buf_len; 291267188Sjkim 292280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(dtls); 293280304Sjkim /* 294280304Sjkim * Three-byte pad at the beginning for type and payload length, plus a 295280304Sjkim * NUL at the end 296280304Sjkim */ 297280304Sjkim unsigned char payload_buf[4 + MIN_PADDING_SIZE]; 298280304Sjkim memset(payload_buf, ' ', sizeof(payload_buf)); 299280304Sjkim payload_buf[sizeof(payload_buf) - 1] = '\0'; 300280304Sjkim payload_buf_len = honest_payload_size(payload_buf); 301267188Sjkim 302280304Sjkim fixture.payload = &payload_buf[0]; 303280304Sjkim fixture.sent_payload_len = payload_buf_len; 304280304Sjkim fixture.expected_return_value = 0; 305280304Sjkim fixture.expected_payload_len = payload_buf_len; 306280304Sjkim fixture.expected_return_payload = ""; 307280304Sjkim EXECUTE_HEARTBEAT_TEST(); 308280304Sjkim} 309267188Sjkim 310267188Sjkimstatic int test_dtls1_heartbleed() 311280304Sjkim{ 312280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(dtls); 313280304Sjkim /* Three-byte pad at the beginning for type and payload length */ 314280304Sjkim unsigned char payload_buf[] = " HEARTBLEED "; 315267188Sjkim 316280304Sjkim fixture.payload = &payload_buf[0]; 317280304Sjkim fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; 318280304Sjkim fixture.expected_return_value = 0; 319280304Sjkim fixture.expected_payload_len = 0; 320280304Sjkim fixture.expected_return_payload = ""; 321280304Sjkim EXECUTE_HEARTBEAT_TEST(); 322280304Sjkim} 323267188Sjkim 324267188Sjkimstatic int test_dtls1_heartbleed_empty_payload() 325280304Sjkim{ 326280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(dtls); 327280304Sjkim /* 328280304Sjkim * Excluding the NUL at the end, one byte short of type + payload length 329280304Sjkim * + minimum padding 330280304Sjkim */ 331280304Sjkim unsigned char payload_buf[MIN_PADDING_SIZE + 3]; 332280304Sjkim memset(payload_buf, ' ', sizeof(payload_buf)); 333280304Sjkim payload_buf[sizeof(payload_buf) - 1] = '\0'; 334267188Sjkim 335280304Sjkim fixture.payload = &payload_buf[0]; 336280304Sjkim fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; 337280304Sjkim fixture.expected_return_value = 0; 338280304Sjkim fixture.expected_payload_len = 0; 339280304Sjkim fixture.expected_return_payload = ""; 340280304Sjkim EXECUTE_HEARTBEAT_TEST(); 341280304Sjkim} 342267188Sjkim 343267188Sjkimstatic int test_dtls1_heartbleed_excessive_plaintext_length() 344280304Sjkim{ 345280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(dtls); 346280304Sjkim /* 347280304Sjkim * Excluding the NUL at the end, one byte in excess of maximum allowed 348280304Sjkim * heartbeat message length 349280304Sjkim */ 350280304Sjkim unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2]; 351280304Sjkim memset(payload_buf, ' ', sizeof(payload_buf)); 352280304Sjkim payload_buf[sizeof(payload_buf) - 1] = '\0'; 353267188Sjkim 354280304Sjkim fixture.payload = &payload_buf[0]; 355280304Sjkim fixture.sent_payload_len = honest_payload_size(payload_buf); 356280304Sjkim fixture.expected_return_value = 0; 357280304Sjkim fixture.expected_payload_len = 0; 358280304Sjkim fixture.expected_return_payload = ""; 359280304Sjkim EXECUTE_HEARTBEAT_TEST(); 360280304Sjkim} 361267188Sjkim 362267188Sjkimstatic int test_tls1_not_bleeding() 363280304Sjkim{ 364280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(tls); 365280304Sjkim /* Three-byte pad at the beginning for type and payload length */ 366280304Sjkim unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" 367280304Sjkim " "; 368280304Sjkim const int payload_buf_len = honest_payload_size(payload_buf); 369267188Sjkim 370280304Sjkim fixture.payload = &payload_buf[0]; 371280304Sjkim fixture.sent_payload_len = payload_buf_len; 372280304Sjkim fixture.expected_return_value = 0; 373280304Sjkim fixture.expected_payload_len = payload_buf_len; 374280304Sjkim fixture.expected_return_payload = 375280304Sjkim "Not bleeding, sixteen spaces of padding"; 376280304Sjkim EXECUTE_HEARTBEAT_TEST(); 377280304Sjkim} 378267188Sjkim 379267188Sjkimstatic int test_tls1_not_bleeding_empty_payload() 380280304Sjkim{ 381280304Sjkim int payload_buf_len; 382267188Sjkim 383280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(tls); 384280304Sjkim /* 385280304Sjkim * Three-byte pad at the beginning for type and payload length, plus a 386280304Sjkim * NUL at the end 387280304Sjkim */ 388280304Sjkim unsigned char payload_buf[4 + MIN_PADDING_SIZE]; 389280304Sjkim memset(payload_buf, ' ', sizeof(payload_buf)); 390280304Sjkim payload_buf[sizeof(payload_buf) - 1] = '\0'; 391280304Sjkim payload_buf_len = honest_payload_size(payload_buf); 392267188Sjkim 393280304Sjkim fixture.payload = &payload_buf[0]; 394280304Sjkim fixture.sent_payload_len = payload_buf_len; 395280304Sjkim fixture.expected_return_value = 0; 396280304Sjkim fixture.expected_payload_len = payload_buf_len; 397280304Sjkim fixture.expected_return_payload = ""; 398280304Sjkim EXECUTE_HEARTBEAT_TEST(); 399280304Sjkim} 400267188Sjkim 401267188Sjkimstatic int test_tls1_heartbleed() 402280304Sjkim{ 403280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(tls); 404280304Sjkim /* Three-byte pad at the beginning for type and payload length */ 405280304Sjkim unsigned char payload_buf[] = " HEARTBLEED "; 406267188Sjkim 407280304Sjkim fixture.payload = &payload_buf[0]; 408280304Sjkim fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; 409280304Sjkim fixture.expected_return_value = 0; 410280304Sjkim fixture.expected_payload_len = 0; 411280304Sjkim fixture.expected_return_payload = ""; 412280304Sjkim EXECUTE_HEARTBEAT_TEST(); 413280304Sjkim} 414267188Sjkim 415267188Sjkimstatic int test_tls1_heartbleed_empty_payload() 416280304Sjkim{ 417280304Sjkim SETUP_HEARTBEAT_TEST_FIXTURE(tls); 418280304Sjkim /* 419280304Sjkim * Excluding the NUL at the end, one byte short of type + payload length 420280304Sjkim * + minimum padding 421280304Sjkim */ 422280304Sjkim unsigned char payload_buf[MIN_PADDING_SIZE + 3]; 423280304Sjkim memset(payload_buf, ' ', sizeof(payload_buf)); 424280304Sjkim payload_buf[sizeof(payload_buf) - 1] = '\0'; 425267188Sjkim 426280304Sjkim fixture.payload = &payload_buf[0]; 427280304Sjkim fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; 428280304Sjkim fixture.expected_return_value = 0; 429280304Sjkim fixture.expected_payload_len = 0; 430280304Sjkim fixture.expected_return_payload = ""; 431280304Sjkim EXECUTE_HEARTBEAT_TEST(); 432280304Sjkim} 433267188Sjkim 434280304Sjkim# undef EXECUTE_HEARTBEAT_TEST 435280304Sjkim# undef SETUP_HEARTBEAT_TEST_FIXTURE 436267188Sjkim 437267188Sjkimint main(int argc, char *argv[]) 438280304Sjkim{ 439280304Sjkim int num_failed; 440267188Sjkim 441280304Sjkim SSL_library_init(); 442280304Sjkim SSL_load_error_strings(); 443267188Sjkim 444280304Sjkim num_failed = test_dtls1_not_bleeding() + 445280304Sjkim test_dtls1_not_bleeding_empty_payload() + 446280304Sjkim test_dtls1_heartbleed() + test_dtls1_heartbleed_empty_payload() + 447280304Sjkim /* 448280304Sjkim * The following test causes an assertion failure at 449280304Sjkim * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g: 450280304Sjkim */ 451280304Sjkim (OPENSSL_VERSION_NUMBER >= 0x1000107fL ? 452280304Sjkim test_dtls1_heartbleed_excessive_plaintext_length() : 0) + 453280304Sjkim test_tls1_not_bleeding() + 454280304Sjkim test_tls1_not_bleeding_empty_payload() + 455280304Sjkim test_tls1_heartbleed() + test_tls1_heartbleed_empty_payload() + 0; 456267188Sjkim 457280304Sjkim ERR_print_errors_fp(stderr); 458267188Sjkim 459280304Sjkim if (num_failed != 0) { 460280304Sjkim printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : ""); 461280304Sjkim return EXIT_FAILURE; 462280304Sjkim } 463280304Sjkim return EXIT_SUCCESS; 464280304Sjkim} 465267188Sjkim 466280304Sjkim#else /* OPENSSL_NO_HEARTBEATS */ 467267188Sjkim 468267188Sjkimint main(int argc, char *argv[]) 469280304Sjkim{ 470280304Sjkim return EXIT_SUCCESS; 471280304Sjkim} 472280304Sjkim#endif /* OPENSSL_NO_HEARTBEATS */ 473