// process input data int receiveData(SSL& ssl, Data& data, bool peek) { if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl.SetError(no_error); ssl.verfiyHandShakeComplete(); if (ssl.GetError()) return -1; if (!ssl.HasData()) processReply(ssl); if (peek) ssl.PeekData(data); else ssl.fillData(data); ssl.useLog().ShowData(data.get_length()); if (ssl.GetError()) return -1; if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) { ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); return SSL_WOULD_BLOCK; } return data.get_length(); }
// send data int sendData(SSL& ssl, const void* buffer, int sz) { int sent = 0; 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()) { // advance sent to prvevious sent + plain size just sent sent = ssl.useBuffers().prevSent + ssl.useBuffers().plainSz; } } ssl.verfiyHandShakeComplete(); if (ssl.GetError()) return -1; for (;;) { int len = min(sz - sent, MAX_RECORD_SIZE); output_buffer out; input_buffer tmp; Data data; if (sent == sz) break; if (ssl.CompressionOn()) { if (Compress(static_cast<const opaque*>(buffer) + sent, len, tmp) == -1) { ssl.SetError(compress_error); return -1; } data.SetData(tmp.get_size(), tmp.get_buffer()); } else data.SetData(len, static_cast<const opaque*>(buffer) + sent); buildMessage(ssl, out, data); ssl.Send(out.get_buffer(), out.get_size()); if (ssl.GetError()) { if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { ssl.useBuffers().plainSz = len; ssl.useBuffers().prevSent = sent; } return -1; } sent += len; } ssl.useLog().ShowData(sent, true); return sent; }
char* ERR_error_string(unsigned long errNumber, char* buffer) { static char* msg = (char*)"Please supply a buffer for error string"; if (buffer) { SetErrorString(YasslError(errNumber), buffer); return buffer; } return msg; }
// process input requests void processReply(SSL& ssl) { if (ssl.GetError()) return; if (DoProcessReply(ssl)) // didn't complete process if (!ssl.getSocket().IsNonBlocking()) { // keep trying now, blocking ok while (!ssl.GetError()) if (DoProcessReply(ssl) == 0) break; } else // user will have try again later, non blocking ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); }
int SSL_accept(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().UseAccept() = AcceptState(ssl->getStates().GetAccept() + 1); } switch (ssl->getStates().GetAccept()) { case ACCEPT_BEGIN : processReply(*ssl); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; case ACCEPT_FIRST_REPLY_DONE : sendServerHello(*ssl); if (!ssl->getSecurity().get_resuming()) { sendCertificate(*ssl); if (ssl->getSecurity().get_connection().send_server_key_) sendServerKeyExchange(*ssl); if(ssl->getCrypto().get_certManager().verifyPeer()) sendCertificateRequest(*ssl); sendServerHelloDone(*ssl); ssl->flushBuffer(); } if (!ssl->GetError()) ssl->useStates().UseAccept() = SERVER_HELLO_DONE; case SERVER_HELLO_DONE : if (!ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; case ACCEPT_SECOND_REPLY_DONE : sendChangeCipher(*ssl); sendFinished(*ssl, server_end); ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; case ACCEPT_FINISHED_DONE : if (ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; case ACCEPT_THIRD_REPLY_DONE : 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; // unknown state } }
// 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 } }