static void AbortTransfers( BOOL abortEp0Transfers, BOOL abortEpxTransfers ) { if (abortEp0Transfers) { AbortTransfer(CONTROL_ENDPT, ENDPT_DIR_IN); AbortTransfer(CONTROL_ENDPT, ENDPT_DIR_OUT); } if (abortEpxTransfers) { AbortTransfer(INTIN_ENDPT, ENDPT_DIR_IN); AbortTransfer(BULKIN_ENDPT, ENDPT_DIR_IN); AbortTransfer(BULKOUT_ENDPT, ENDPT_DIR_OUT); } }
// blocking call starts a rx or tx transaction static DWORD SendRecvData( UINT32 epNum, DWORD dir, UINT8 *pData, UINT32 cbDataLen, DWORD flags ) { DWORD dwStartSec, dwSec; DWORD dwRet; EPTransfer* pTransfer = &m_epTransfers[epNum]; USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbdbg:+SendRecvData. ep%d\r\n", epNum)); dwStartSec = OEMKitlGetSecs(); // start rx or tx transfer StartTransfer(epNum, dir, pData, cbDataLen, flags); // loop until all data sent while(pTransfer->status & USBDBG_TRANSFER_STATUS_INPROGRESS) { UsbRndis_EventHandler(); dwSec = OEMKitlGetSecs(); // timed out sending data? if ((INT32)(dwSec - dwStartSec) > SEND_RECV_TIME_OUT) { USBDBGMSG(USBDBG_ZONE_ERROR, ( L"ERROR!UsbDbg: ep%d dir=%d timed out tx/rx data." L"dwSec=%d, dwStartSec=%d\r\n", epNum, dir, dwSec, dwStartSec)); dwRet = ERROR_TIMEOUT; AbortTransfer(epNum, dir); goto clean; } } if (pTransfer->status & USBDBG_TRANSFER_STATUS_COMPLETE) { dwRet = ERROR_SUCCESS; } else { dwRet = ERROR_IO_INCOMPLETE; } clean: USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbdbg:-SendRecvData. ep%d\r\n", epNum)); return dwRet; }
void CfEncryptGetFile(ServerFileGetState *args) /* Because the stream doesn't end for each file, we need to know the exact number of bytes transmitted, which might change during encryption, hence we need to handle this with transactions */ { int fd, n_read, cipherlen, finlen; off_t total = 0, count = 0; char sendbuffer[CF_BUFSIZE + 256], out[CF_BUFSIZE], filename[CF_BUFSIZE]; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; int blocksize = CF_BUFSIZE - 4 * CF_INBAND_OFFSET; EVP_CIPHER_CTX ctx; char *key, enctype; struct stat sb; ConnectionInfo *conn_info = &args->connect->conn_info; key = (args->connect)->session_key; enctype = (args->connect)->encryption_type; TranslatePath(filename, args->replyfile); stat(filename, &sb); Log(LOG_LEVEL_DEBUG, "CfEncryptGetFile('%s'), size = %" PRIdMAX, filename, (intmax_t) sb.st_size); /* Now check to see if we have remote permission */ if (!TransferRights(filename, args, &sb)) { RefuseAccess(args->connect, args->buf_size, ""); FailedTransfer(conn_info); } EVP_CIPHER_CTX_init(&ctx); if ((fd = open(filename, O_RDONLY)) == -1) { Log(LOG_LEVEL_ERR, "Open error of file '%s'. (open: %s)", filename, GetErrorStr()); FailedTransfer(conn_info); } else { int div = 3; if (sb.st_size > 10485760L) /* File larger than 10 MB, checks every 64kB */ { div = 32; } while (true) { memset(sendbuffer, 0, CF_BUFSIZE); if ((n_read = read(fd, sendbuffer, blocksize)) == -1) { Log(LOG_LEVEL_ERR, "Read failed in EncryptGetFile. (read: %s)", GetErrorStr()); break; } off_t savedlen = sb.st_size; if (count++ % div == 0) /* Don't do this too often */ { Log(LOG_LEVEL_DEBUG, "Restatting '%s' - size %d", filename, n_read); if (stat(filename, &sb)) { Log(LOG_LEVEL_ERR, "Cannot stat file '%s' (stat: %s)", filename, GetErrorStr()); break; } } if (sb.st_size != savedlen) { AbortTransfer(conn_info, filename); break; } total += n_read; if (n_read > 0) { EVP_EncryptInit_ex(&ctx, CfengineCipher(enctype), NULL, key, iv); if (!EVP_EncryptUpdate(&ctx, out, &cipherlen, sendbuffer, n_read)) { FailedTransfer(conn_info); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } if (!EVP_EncryptFinal_ex(&ctx, out + cipherlen, &finlen)) { FailedTransfer(conn_info); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } } if (total >= savedlen) { if (SendTransaction(conn_info, out, cipherlen + finlen, CF_DONE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } break; } else { if (SendTransaction(conn_info, out, cipherlen + finlen, CF_MORE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); close(fd); EVP_CIPHER_CTX_cleanup(&ctx); return; } } } } EVP_CIPHER_CTX_cleanup(&ctx); close(fd); }
// Called by RndisMin & UsbRndis to get "interesting" events from PDD // UINT32 UsbRndis_EventHandler( ) { USBDBG_MSG msg = USBDBG_MSG_NOMSG; DWORD retVal; DWORD epNum; static USB_DEVICE_REQUEST pendingUdr; static BOOL fProcessingSetupRequest = FALSE; USBDBGMSG(USBDBG_ZONE_EVENT, (L"usbdbg:+UsbRndis_EventHandler\r\n")); // call PDD to get any interesting events retVal = m_pddIfc.pfnEventHandler(&msg, &m_MsgParamBuf[0]); //quit if error if (retVal != ERROR_SUCCESS) { USBDBGMSG(USBDBG_ZONE_ERROR, ( L"ERROR!usbdbg:UsbRndis_EventHandler\r\n")); goto clean; } switch (msg) { // a packet received on an EP case USBDBG_MSG_EP_RX_PKT: { epNum = *((DWORD*)m_MsgParamBuf); ContinueRxTransfer(epNum); break; } // a packet sent on an EP case USBDBG_MSG_EP_TX_PKT: { epNum = *((DWORD*)m_MsgParamBuf); ContinueTxTransfer(epNum); break; } // set up packet recvd case USBDBG_MSG_SETUP_PACKET: { USB_DEVICE_REQUEST udr = *((USB_DEVICE_REQUEST*) m_MsgParamBuf); BOOL fProcessRndisMsg = FALSE; // if a transfer is already in progress on EP0, mark this // setup packet pending and return to unwind stack. if (fProcessingSetupRequest) { m_fSetupCancelled = TRUE; pendingUdr = udr; // stop any transfers on EP0 if (m_epTransfers[0].status & USBDBG_TRANSFER_STATUS_INPROGRESS) { AbortTransfer(CONTROL_ENDPT, ENDPT_DIR_RX); AbortTransfer(CONTROL_ENDPT, ENDPT_DIR_TX); } goto clean; } else { m_fSetupCancelled = FALSE; } fProcessingSetupRequest = TRUE; ProcessSetupPacket(&udr, &fProcessRndisMsg); fProcessingSetupRequest = FALSE; //rndis msg received? if (fProcessRndisMsg) ProcessRndisMsg(m_ep0MsgRxBuffer, udr.wLength); // while a setup packet was being processed another might have come // in. udr's processing was cancelled and the pending udr was stored // in m_pendingUdr. while (m_fSetupCancelled) { m_fSetupCancelled = FALSE; fProcessingSetupRequest = TRUE; ProcessSetupPacket(&pendingUdr, &fProcessRndisMsg); fProcessingSetupRequest = FALSE; if (fProcessRndisMsg) ProcessRndisMsg(m_ep0MsgRxBuffer, udr.wLength); } break; } case USBDBG_MSG_BUS_EVENT_DETACH: case USBDBG_MSG_BUS_EVENT_SUSPEND: case USBDBG_MSG_BUS_EVENT_RESET: { // tell rndismin layer RndisPdd_SetRndisState(TRUE); // abort all transfers AbortTransfers(TRUE, TRUE); // bus speed is determined, update ep's maxpktsize UpdateUSBDesc(); break; } default: break; } clean: USBDBGMSG(USBDBG_ZONE_EVENT, (L"usbdbg:-UsbRndis_EventHandler.msg=%d\r\n", msg)); return msg; }