vector<uint8_t> SslWrapper::get() { if (this->url.isUseSsl()) { Log::info << "Start requesting with ssl (it must be hard)" << endl; /* Client Server ClientHello ----1----> ServerHello Certificate* ServerKeyExchange* CertificateRequest* <---2----- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished ----3----> [ChangeCipherSpec] <---4----- Finished Application Data <---5----> Application Data */ //phrase 1 sendClientHello(); //phrase 2 //receive data try { pair<Record, Record> records = receiveServerHello(); Record &serverCertificate = records.second; Record &serverHello = records.first; Log::info << "Make \"client_key_exchange\" record (hard)" << endl; //phrase 3 sendClientCertificate(serverHello, serverCertificate); throw string("Deadline is coming. So that I stop here"); //phrase 4: receive finished message try { receiveServerFinished(); //phrase 5: send request sendData(url.httpGetRequest()); //phrase 6: receive data return receiveData(); } catch (string const& msg) { Log::err << msg << endl; } } catch (string const& err) { Log::err << err << endl; } // Log::warn << "Return empty result because of occurred error" << endl; return vector<uint8_t>(); } Log::info << "Send request without using ssl" << endl; this->connection->send(this->url.httpGetRequest()); return this->connection->receive(); }
// if you get an error from connect see note at top of README int SSL_connect(SSL* ssl) { if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl->SetError(no_error); if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { ssl->SetError(no_error); ssl->SendWriteBuffered(); if (!ssl->GetError()) ssl->useStates().UseConnect() = ConnectState(ssl->getStates().GetConnect() + 1); } ClientState neededState; switch (ssl->getStates().GetConnect()) { case CONNECT_BEGIN : sendClientHello(*ssl); if (!ssl->GetError()) ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; case CLIENT_HELLO_SENT : neededState = ssl->getSecurity().get_resuming() ? serverFinishedComplete : serverHelloDoneComplete; while (ssl->getStates().getClient() < neededState) { if (ssl->GetError()) break; processReply(*ssl); // if resumption failed, reset needed state if (neededState == serverFinishedComplete) if (!ssl->getSecurity().get_resuming()) neededState = serverHelloDoneComplete; } if (!ssl->GetError()) ssl->useStates().UseConnect() = FIRST_REPLY_DONE; case FIRST_REPLY_DONE : if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificate(*ssl); if (!ssl->getSecurity().get_resuming()) sendClientKeyExchange(*ssl); if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificateVerify(*ssl); sendChangeCipher(*ssl); sendFinished(*ssl, client_end); ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseConnect() = FINISHED_DONE; case FINISHED_DONE : if (!ssl->getSecurity().get_resuming()) while (ssl->getStates().getClient() < serverFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } if (!ssl->GetError()) ssl->useStates().UseConnect() = SECOND_REPLY_DONE; case SECOND_REPLY_DONE : ssl->verifyState(serverFinishedComplete); ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; } return SSL_SUCCESS; default : return SSL_FATAL_ERROR; // unkown state } }
void ovListener (ovStruct_t *ovP) { int sock; uchar buff[5000]; // uchar is important int bytes_recv, index, i, j; int set = 0; int remBytes = 0; ushort RecordHdrLengthRecvd = 0; jsonData_t* jsonData = ovP->jsonData; int ssl_len; int saveLen = 0; uchar saveBuff[5000]; log_info(fp, "Entering OpenVPN Listener Loop..."); fflush(fp); while(1) { bytes_recv = recv(ovP->sock,&buff[0], 3000, 0); log_debug(fp, "OpenVPN Bytes_recv = %d, ", bytes_recv); fflush(fp); if (bytes_recv == -1) { perror("-1: Error during recv: "); exit(1); } if (bytes_recv == 0) { log_error(fp, "OpenVPN: Error: recvFunction: sock closed in recv, bytes_Recv = 0"); fflush(fp); sleep(10); // This is so that the main has time to gather stats exit(1); // No point keeping this since the sock is gone } switch((buff[0] & P_KEYID_MASK) >> 3) { case P_CONTROL_HARD_RESET_SERVER_V2: log_info(fp, " <- OV: P_CONTROL_HARD_RESET_SERVER_V2"); fflush(fp); ovP->toAck = GET_BE32(&buff[50]); memcpy(ovP->toSessionID, &buff[1], 8); log_info(fp, "toAck = %d", ovP->toAck); fflush(fp); log_info(fp, "\nOpenVPN toSession ID: "); for (j=0;j<8;j++) printf("%2x ", ovP->toSessionID[j]); fflush(stdout); sendAckV1(ovP, jsonData); sleep(1); sendClientHello(ovP, jsonData); break; case P_ACK_V1: log_info(fp, " <- OV: P_ACK_V1"); fflush(fp); break; case P_CONTROL_V1: log_info(fp, " <- OV: P_CONTROL_V1"); fflush(fp); // Note that if saveLen is non Zero, then we have a continued // SSL packet and we need to keep collecting the SSL pkt till // we get the complete pkt. if (saveLen != 0) { // Continuing pkts do not have ACK data, and thus their // len is 42 bytes. ovP->toAck = GET_BE32(&buff[38]); log_info(fp, "toAck: %d", ovP->toAck); fflush(fp); memcpy(&saveBuff[saveLen], &buff[42], bytes_recv-42); saveLen = saveLen + bytes_recv - 42; saveBuff[3] = saveBuff[3] & 0x7F; // clears the MSB flag ssl_len=GET_BE16(&saveBuff[3]); if (saveLen >= (ssl_len+5)) { log_info(fp, "We have complete SSL pkt %d of %d", saveLen, ssl_len+5); fflush(fp); // Control falls down to decoding the SSL hdr memcpy(buff, saveBuff, (ssl_len+5)); index=0; // But, first set the next ssl pkt if partially recvd. memcpy(saveBuff, &saveBuff[ssl_len+5], saveLen-(ssl_len+5)); saveLen = saveLen - (ssl_len+5); log_info(fp, "We have next partial SSL pkt of size %d", saveLen); fflush(fp); } else { log_info(fp, "We have partial SSL pkt %d of %d", saveLen, ssl_len+5); fflush(fp); sendAckV1(ovP, jsonData); continue; } } else { ovP->toAck = GET_BE32(&buff[50]); // This occurs 1st time only for a complete or a partial pkt index = 54; buff[index+3] = buff[index+3] & 0x7F; // clears the MSB flag ssl_len = GET_BE16(&buff[index+3]); // If there is more than ssl_len+54+5 then we need to look for the // 2nd SSL pkt now. if (bytes_recv > ssl_len+54+5) { int left = bytes_recv - (ssl_len+54+5); log_info(fp, "Left over bytes: %d", left); fflush(fp); memcpy(&saveBuff[saveLen], &buff[ssl_len+54+5], left); saveLen += left; } } // Check in the pkt now to see the SSL Pkt type // Assuming 54 bytes OpenVPN Hdr, it the peer also is acking // the Client Hello pkt, we need to jump these many bytes to // start decoding the SSL header. switch(buff[index]) { case change_cipher_spec: log_info(fp, " <- SSL: Change Cipher: %d", ssl_len+5); break; case alert: log_info(fp, " <- SSL: Alert: %d", ssl_len+5); break; case handshake: log_info(fp, " <- SSL: Handshake: %d", ssl_len+5); break; case application_data: log_info(fp, " <- SSL: App data: %d", ssl_len+5); break; default: log_error(fp, " <- SSL: Error pkt recvd: %d, ", buff[0]); } if (buff[index] == change_cipher_spec) { break; } if (buff[index] == alert) { break; } // TBD: Logic needed to read multiple Handshake msgs in 1 msg switch(buff[index+5]) { case hello_request: log_info(fp, " <- Handshake Type: Hello Request"); break; case client_hello: log_info(fp, " <- Handshake Type: Client Hello"); break; case server_hello: log_info(fp, " <- Handshake Type: Server Hello"); //recvServerHello(ovP); break; case certificate: log_info(fp, " <- Handshake Type: Certificate"); //recvCertificate (ovP); break; case server_key_exchange: log_info(fp, " <- Handshake Type: Server Key Exchange"); //ovP->handshakeResp |= set; break; case certificate_request: log_info(fp, " <- Handshake Type: Certificate Request"); // TBD: Check if Server Hello Done is also in this message // We need a smarter way to parse multiple handshake msgs // so that we dont use this kludge here if (buff[bytes_recv-4] == 0x0E) { log_info(fp, " <- Handshake Type: Server Hello Done"); ovSendClientCertificate(ovP, jsonData); ovSendClientKeyExchange(ovP, jsonData); } break; case server_hello_done: log_info(fp, " <- Handshake Type: Server Hello Done"); //recvServerHelloDone(ovP); break; case certificate_verify: log_info(fp, " <- Handshake Type: Certificate Verify"); break; break; case client_key_exchange: log_info(fp, " <- Handshake Type: Client Key Exchange"); break; break; case finished: log_info(fp, " <- Handshake Type: Finished"); break; default: log_info(fp, " <- Handshake Type: Unknown"); } sendAckV1(ovP, jsonData); break; default: log_error(fp, " <- OV: Error pkt recvd: %d, ", buff[0]); // We have some junk data. Throw it away log_info(fp, "..discarding %d len data\n", bytes_recv); continue; } #ifdef DEBUG for (j=0;j<i;j++) printf("%2x ", buff[j]); fflush(fp); #endif } exit(0); }