char ioReadChange(char pin) { char mask = 1 << (pin & MASK_PIN); char previousValue; if(pin & MASK_D) { previousValue = portDMemory & mask; } else if(pin & MASK_C) { previousValue = portCMemory & mask; } else { previousValue = portBMemory & mask; } char newValue = ioRead(pin); if(newValue != previousValue) { // looks like a change, better double check _delay_us(DEBOUNCE_TIME); newValue = ioRead(pin); } if(previousValue != newValue) { if(pin & MASK_D) { portDMemory ^= mask; } else if(pin & MASK_C) { portCMemory ^= mask; } else { portBMemory ^= mask; } if(newValue) { return IO_RISE; } else { return IO_FALL; } } else { if(newValue) { return IO_HIGH; } else { return IO_LOW; } } }
/*********************************************************************************************************************************** Decompress data ***********************************************************************************************************************************/ static Buffer * testDecompress(IoFilter *decompress, Buffer *compressed, size_t inputSize, size_t outputSize) { Buffer *decompressed = bufNew(1024 * 1024); Buffer *output = bufNew(outputSize); ioBufferSizeSet(inputSize); IoFilterGroup *filterGroup = ioFilterGroupNew(); ioFilterGroupAdd(filterGroup, decompress); IoRead *read = ioBufferReadNew(compressed); ioReadFilterGroupSet(read, filterGroup); ioReadOpen(read); while (!ioReadEof(read)) { ioRead(read, output); bufCat(decompressed, output); bufUsedZero(output); } ioReadClose(read); bufFree(output); memContextFree(((GzipDecompress *)ioFilterDriver(decompress))->memContext); return decompressed; }
/*********************************************************************************************************************************** Read all IO into a buffer ***********************************************************************************************************************************/ Buffer * ioReadBuf(IoRead *read) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(IO_READ, read); FUNCTION_TEST_END(); ASSERT(read != NULL); Buffer *result = NULL; MEM_CONTEXT_TEMP_BEGIN() { // Read IO into the buffer result = bufNew(0); do { bufResize(result, bufSize(result) + ioBufferSize()); ioRead(read, result); } while (!ioReadEof(read)); // Resize the buffer and move to calling context bufResize(result, bufUsed(result)); bufMove(result, MEM_CONTEXT_OLD()); } MEM_CONTEXT_TEMP_END(); FUNCTION_TEST_RETURN(result); }
static bool exceptionHandler(hostContext_t* context) { uint8_t* code = (uint8_t*)context->eip; uint8_t im = code[1]; if (*code == 0xE6) { ioWrite(im,(ioData_t*)&context->al,1); //printf("0x%08X: OUT Ib (0x%02X) eAX AL (0x%08X)\n",context->eip,im,context->al); context->eip += 2; return true; } if (*code == 0xE7) { ioWrite(im,(ioData_t*)&context->eax,4); //printf("0x%08X: OUT Ib (0x%02X) eAX (0x%08X)\n",context->eip,im,context->eax); context->eip += 2; return true; } if (*code == 0xEE) { //printf("0x%08X: OUT DX (0x%04X) AL (0x%02X)\n",context->eip,context->dx,context->al); ioWrite(context->dx,(ioData_t*)&context->al,1); context->eip += 1; return true; } if (*code == 0xEF) { //printf("0x%08X: OUT DX (0x%04X) eAX (0x%08X)\n",context->eip,context->dx,context->eax); ioWrite(context->dx,(ioData_t*)&context->eax,4); context->eip += 1; return true; } if (*code == 0xED) { //printf("0x%08X: in eax, dx (0x%04X) // ecx: %i\n",context->eip,context->dx,context->ecx); ioRead(context->dx,(ioData_t*)&context->eax,4); context->eip += 1; return true; } printf("Unhandled exception at 0x%08X!\n",context->eip); return false; }
/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // Additional coverage not provided by testing with actual certificates // ***************************************************************************************************************************** if (testBegin("asn1ToStr(), tlsClientHostVerify(), and tlsClientHostVerifyName()")) { TEST_ERROR(asn1ToStr(NULL), CryptoError, "TLS certificate name entry is missing"); TEST_ERROR( tlsClientHostVerifyName( strNew("host"), strNewN("ab\0cd", 5)), CryptoError, "TLS certificate name contains embedded null"); TEST_ERROR(tlsClientHostVerify(strNew("host"), NULL), CryptoError, "No certificate presented by the TLS server"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("host"), strNew("**")), false, "invalid pattern"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("host"), strNew("*.")), false, "invalid pattern"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("a.bogus.host.com"), strNew("*.host.com")), false, "invalid host"); } // ***************************************************************************************************************************** if (testBegin("TlsClient verification")) { TlsClient *client = NULL; // Connection errors // ------------------------------------------------------------------------------------------------------------------------- TEST_ASSIGN(client, tlsClientNew(strNew("99.99.99.99.99"), 9443, 0, true, NULL, NULL), "new client"); TEST_ERROR( tlsClientOpen(client), HostConnectError, "unable to get address for '99.99.99.99.99': [-2] Name or service not known"); TEST_ASSIGN(client, tlsClientNew(strNew("localhost"), 9443, 100, true, NULL, NULL), "new client"); TEST_ERROR(tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:9443': [111] Connection refused"); // Certificate location and validation errors // ------------------------------------------------------------------------------------------------------------------------- // Add test hosts if (system( // {uncoverable_branch} "echo \"127.0.0.1 test.pgbackrest.org host.test2.pgbackrest.org test3.pgbackrest.org\" |" " sudo tee -a /etc/hosts > /dev/null") != 0) { THROW(AssertError, "unable to add test hosts to /etc/hosts"); // {uncovered+} } // Start server to test various certificate errors testTlsServerAltName(); TEST_ERROR( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, true, strNew("bogus.crt"), strNew("/bogus"))), CryptoError, "unable to set user-defined CA certificate location: [33558530] No such file or directory"); TEST_ERROR( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, true, NULL, strNew("/bogus"))), CryptoError, "unable to verify certificate presented by 'localhost:9443': [20] unable to get local issuer certificate"); TEST_RESULT_VOID( tlsClientOpen( tlsClientNew(strNew("test.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), "success on valid ca file and match common name"); TEST_RESULT_VOID( tlsClientOpen( tlsClientNew(strNew("host.test2.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), "success on valid ca file and match alt name"); TEST_ERROR( tlsClientOpen( tlsClientNew(strNew("test3.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), CryptoError, "unable to find hostname 'test3.pgbackrest.org' in certificate common name or subject alternative names"); TEST_ERROR( tlsClientOpen( tlsClientNew(strNew("localhost"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX ".crt", testRepoPath()), NULL)), CryptoError, "unable to verify certificate presented by 'localhost:9443': [20] unable to get local issuer certificate"); TEST_RESULT_VOID( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, false, NULL, NULL)), "success on no verify"); } // ***************************************************************************************************************************** if (testBegin("TlsClient general usage")) { TlsClient *client = NULL; // Reset statistics tlsClientStatLocal = (TlsClientStat){0}; TEST_RESULT_STR(tlsClientStatStr(), NULL, "no stats yet"); testTlsServer(); ioBufferSizeSet(12); TEST_ASSIGN(client, tlsClientNew(strNew(TLS_TEST_HOST), 9443, 500, true, NULL, NULL), "new client"); TEST_RESULT_VOID(tlsClientOpen(client), "open client"); const Buffer *input = BUFSTRDEF("some protocol info"); TEST_RESULT_VOID(ioWrite(tlsClientIoWrite(client), input), "write input"); ioWriteFlush(tlsClientIoWrite(client)); TEST_RESULT_STR(strPtr(ioReadLine(tlsClientIoRead(client))), "something:0", "read line"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); Buffer *output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 12, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "some content", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(8); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 8, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "AND MORE", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(12); TEST_ERROR( ioRead(tlsClientIoRead(client), output), FileReadError, "unable to read data from 'tls.test.pgbackrest.org:9443' after 500ms"); // ------------------------------------------------------------------------------------------------------------------------- input = BUFSTRDEF("more protocol info"); TEST_RESULT_VOID(tlsClientOpen(client), "open client again (it is already open)"); TEST_RESULT_VOID(ioWrite(tlsClientIoWrite(client), input), "write input"); ioWriteFlush(tlsClientIoWrite(client)); output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 12, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "0123456789AB", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 0, "read no output after eof"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), true, " check eof = true"); TEST_RESULT_BOOL(tlsClientStatStr() != NULL, true, "check statistics exist"); TEST_RESULT_VOID(tlsClientFree(client), "free client"); } FUNCTION_HARNESS_RESULT_VOID(); }
// Waits for data on any handle and read it. Returns the amount of handles where data have been read. int ioReadAll(struct s_io_state *iostate) { int ret; int i; #if defined(IO_LINUX) || defined(IO_BSD) fd_set fdset; struct timeval seltimeout; int fd, fdh; seltimeout.tv_sec = iostate->timeout; seltimeout.tv_usec = 0; fdh = 0; FD_ZERO(&fdset); for(i=0; i<iostate->max; i++) { if(iostate->handle[i].enabled) { fd = iostate->handle[i].fd; FD_SET(fd, &fdset); if(fdh < (fd+1)) { fdh = (fd+1); } } } ret = 0; if(!(fdh < 0)) { if(select(fdh, &fdset, NULL, NULL, &seltimeout) > 0) { for(i=0; i<iostate->max; i++) { if(iostate->handle[i].enabled) { if(FD_ISSET(iostate->handle[i].fd, &fdset)) { ioPreRead(iostate, i); if(ioRead(iostate, i) > 0) { ret++; } } } } } } #elif defined(IO_WINDOWS) HANDLE events[iostate->max]; int fdc; fdc = 0; for(i=0; i<iostate->max; i++) { if(iostate->handle[i].enabled) { ioPreRead(iostate, i); if(iostate->handle[i].ovlr_used) { events[fdc] = iostate->handle[i].ovlr.hEvent; fdc++; } } } ret = 0; if(fdc > 0) { WaitForMultipleObjects(fdc, events, FALSE, (iostate->timeout * 1000)); for(i=0; i<iostate->max; i++) { if(ioRead(iostate, i) > 0) { ret++; } } } else { Sleep(iostate->timeout * 1000); } #else #error not implemented ret = 0; #endif return ret; }