diff --git a/microscript/ILibDuktape_TlsStream.c b/microscript/ILibDuktape_TlsStream.c deleted file mode 100644 index e1dd424..0000000 --- a/microscript/ILibDuktape_TlsStream.c +++ /dev/null @@ -1,561 +0,0 @@ -#include "duktape.h" -#include "ILibDuktape_Helpers.h" -#include "ILibDuktapeModSearch.h" -#include "ILibDuktape_DuplexStream.h" -#include "ILibDuktape_EventEmitter.h" - -#ifndef MICROSTACK_NOTLS -#include -#include -#endif - -#include "../microstack/ILibCrypto.h" - -#define ILibDuktape_TlsStream_Ptr "\xFF_ILibDuktape_TLSSTREAM_PTR" -#define ILibDuktape_TlsStream2Cert "\xFF_TLS_CERT" - -#define MEMORYCHUNKSIZE 4096 -int ILibDuktape_TlsStream_ctx2stream = -1; - -typedef struct ILibDuktape_TlsStream_Data -{ - duk_context *ctx; - void *tlsObject; - void *chain; - int isClient; - ILibDuktape_EventEmitter *emitter; - char *decryptedBuffer; - int decryptedBuffer_mallocSize; - int decryptedBuffer_beginPointer; - int decryptedBuffer_endPointer; - int decryptedBuffer_unshiftedBytes; - int decryptedBuffer_maxSize; - - int rejectUnauthorized; - void *OnVerify; - void *OnServerSNI; - - int ProcessEncryptedBuffer_Active; - - SSL* ssl; - SSL_CTX *ssl_ctx; - BIO *readBio, *writeBio; - BUF_MEM *readBioBuffer, *writeBioBuffer; - int TLSHandshakeCompleted; - ILibDuktape_DuplexStream *clear; - ILibDuktape_DuplexStream *encrypted; - int encrypted_unshiftBytes; -}ILibDuktape_TlsStream_Data; - - -void ILibDuktape_TlsStream_X509_PUSH(duk_context *ctx, X509* cert) -{ - char hash[UTIL_SHA384_HASHSIZE]; - char fingerprint[150]; - - util_keyhash2(cert, hash); - util_tohex2(hash, UTIL_SHA384_HASHSIZE, fingerprint); - - duk_push_object(ctx); // [cert] - duk_push_string(ctx, fingerprint); // [cert][fingerprint] - duk_put_prop_string(ctx, -2, "fingerprint"); // [cert] -} -ILibTransport_DoneState ILibDuktape_TlsStream_ProcessEncryptedBuffer(ILibDuktape_TlsStream_Data *tlsdata) -{ - int j, first = 1; - - if (tlsdata->ProcessEncryptedBuffer_Active == 0) - { - tlsdata->ProcessEncryptedBuffer_Active = 1; - tlsdata->encrypted_unshiftBytes = 0; - BIO_clear_retry_flags(tlsdata->writeBio); - - while ((j = (int)tlsdata->writeBioBuffer->length) > 0 && tlsdata->encrypted->readableStream->paused == 0) - { - if (first == 1) - { - first = 0; - } - else - { - tlsdata->encrypted_unshiftBytes = 0; - BIO_clear_retry_flags(tlsdata->writeBio); - } - - do - { - ILibDuktape_DuplexStream_WriteData(tlsdata->encrypted, tlsdata->writeBioBuffer->data, (int)tlsdata->writeBioBuffer->length); - } while (tlsdata->encrypted_unshiftBytes > 0); - if (tlsdata->encrypted_unshiftBytes == 0) - { - tlsdata->writeBioBuffer->data += (int)tlsdata->writeBioBuffer->length; - tlsdata->writeBioBuffer->length = 0; - } - } - tlsdata->ProcessEncryptedBuffer_Active = 0; - return(tlsdata->writeBioBuffer->length > 0 ? ILibTransport_DoneState_INCOMPLETE : ILibTransport_DoneState_COMPLETE); - } - else - { - return(ILibTransport_DoneState_ERROR); - } -} -ILibTransport_DoneState ILibDuktape_TlsStream_Clear_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - - SSL_write(data->ssl, buffer, bufferLen); - return(ILibDuktape_TlsStream_ProcessEncryptedBuffer(data)); -} -void ILibDuktape_TlsStream_Clear_EndSink(ILibDuktape_DuplexStream *stream, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - if (ILibIsRunningOnChainThread(data->chain) != 0 && data->encrypted->writableStream->pipedReadable != NULL) - { - duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [stream] - duk_get_prop_string(data->ctx, -1, "end"); // [stream][end] - duk_swap_top(data->ctx, -2); // [end][this] - if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.unencrypted.end(): Error dispatching 'end' upstream "); } - duk_pop(data->ctx); // ... - } -} -void ILibDuktape_TlsStream_Clear_PauseSink_Chain(void *chain, void *user) -{ - if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; } - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - - duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable] - duk_get_prop_string(data->ctx, -1, "pause"); // [readable][pause] - duk_swap_top(data->ctx, -2); // [pause][this] - if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.pause(): Error pausing upstream object "); }; - duk_pop(data->ctx); // ... -} -void ILibDuktape_TlsStream_Clear_PauseSink(ILibDuktape_DuplexStream *sender, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->PauseHandler != NULL) - { - data->encrypted->writableStream->pipedReadable_native->paused = 1; - data->encrypted->writableStream->pipedReadable_native->PauseHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user); - } - else if (data->encrypted->writableStream->pipedReadable != NULL) - { - if (ILibIsRunningOnChainThread(data->chain) != 0) - { - ILibDuktape_TlsStream_Clear_PauseSink_Chain(NULL, data); - } - else - { - // We're on the wrong thread to resume the upstream object - ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_PauseSink_Chain, data); - } - } -} -void ILibDuktape_TlsStream_Clear_ResumeSink_Chain(void *chain, void *user) -{ - if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; } - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - - duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable] - duk_get_prop_string(data->ctx, -1, "resume"); // [readable][resume] - duk_swap_top(data->ctx, -2); // [resume][this] - if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.resume(): Error resuming upstream object "); }; - duk_pop(data->ctx); // ... -} -void ILibDuktape_TlsStream_Clear_ResumeSink(ILibDuktape_DuplexStream *sender, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->ResumeHandler != NULL) - { - data->encrypted->writableStream->pipedReadable_native->paused = 0; - data->encrypted->writableStream->pipedReadable_native->ResumeHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user); - } - else if (data->encrypted->writableStream->pipedReadable != NULL) - { - if (ILibIsRunningOnChainThread(data->chain) != 0) - { - ILibDuktape_TlsStream_Clear_ResumeSink_Chain(NULL, data); - } - else - { - // We're on the wrong thread to resume the upstream object - ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_ResumeSink_Chain, data); - } - } -} -int ILibDuktape_TlsStream_Clear_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - - if (unshiftBytes == data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer) - { - data->decryptedBuffer_unshiftedBytes = -1; - } - else - { - data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer - unshiftBytes; - data->decryptedBuffer_unshiftedBytes = unshiftBytes; - } - return(unshiftBytes); -} - -ILibTransport_DoneState ILibDuktape_TlsStream_Encrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - int j; - - //int len = BIO_write(data->writeBio, buffer, bufferLen); - BIO_write(SSL_get_rbio(data->ssl), buffer, bufferLen); - int sslerror; - - if (data->TLSHandshakeCompleted == 0) - { - switch ((sslerror = SSL_do_handshake(data->ssl))) - { - case 0: - // Handshake Failed! - while ((sslerror = ERR_get_error()) != 0) - { - ERR_error_string_n(sslerror, ILibScratchPad, sizeof(ILibScratchPad)); - } - // TODO: We should probably do something - break; - case 1: - data->TLSHandshakeCompleted = 1; - if (ILibIsRunningOnChainThread(data->chain) != 0) - { - // We're on the Duktape Thread - duk_push_heapptr(data->ctx, data->tlsObject); // [TLS] - duk_get_prop_string(data->ctx, -1, "emit"); // [TLS][emit] - duk_swap_top(data->ctx, -2); // [emit][this] - duk_push_string(data->ctx, "connect"); // [emit][this][connect] - if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.connect(): "); } - duk_pop(data->ctx); // ... - } - else - { - // Need to context switch to the Duktape Thread - } - ILibDuktape_TlsStream_ProcessEncryptedBuffer(data); - break; - default: - // SSL_WANT_READ most likely - sslerror = SSL_get_error(data->ssl, sslerror); - ILibDuktape_TlsStream_ProcessEncryptedBuffer(data); - break; - } - return(ILibTransport_DoneState_COMPLETE); - } - else - { - while ((j = SSL_read(data->ssl, data->decryptedBuffer + data->decryptedBuffer_endPointer, data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer)) > 0) - { - // We got new TLS Data - if (j > 0) - { - data->decryptedBuffer_endPointer += j; - if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer == 0) - { - data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize); - if((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254); - } - } - } - if (j < 0) - { - sslerror = SSL_get_error(data->ssl, j); - if (data->writeBioBuffer->length > 0) - { - ILibDuktape_TlsStream_ProcessEncryptedBuffer(data); - } - } - } - - // - // Event data up the stack, to process any data that is available - // - do - { - data->decryptedBuffer_unshiftedBytes = 0; - ILibDuktape_DuplexStream_WriteData(data->clear, data->decryptedBuffer + data->decryptedBuffer_beginPointer, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer); - } while (data->decryptedBuffer_unshiftedBytes > 0); - if (data->decryptedBuffer_unshiftedBytes == 0) { data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer = 0; } - - - // - // Check to see if we need to move any data, to maximize buffer space - // - if (data->decryptedBuffer_beginPointer != 0) - { - // - // We can save some cycles by moving the data back to the top - // of the buffer, instead of just allocating more memory. - // - char *temp = data->decryptedBuffer + data->decryptedBuffer_beginPointer; - - memmove_s(data->decryptedBuffer, data->decryptedBuffer_mallocSize, temp, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer); - data->decryptedBuffer_endPointer -= data->decryptedBuffer_beginPointer; - data->decryptedBuffer_beginPointer = 0; - } - - // - // Check to see if we should grow the buffer - // - if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer < 1024 && (data->decryptedBuffer_maxSize == 0 || data->decryptedBuffer_mallocSize < data->decryptedBuffer_maxSize)) - { - data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize); - if ((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254); - } - - return(data->clear->readableStream->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE); -} -void ILibDuktape_TlsStream_Encrypted_EndSink(ILibDuktape_DuplexStream *stream, void *user) -{ -} -void ILibDuktape_TlsStream_Encrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user) -{ - // Don't need to do anythign, becuase the 'ILibDuktape_TlsStream_ProcessEncryptedBuffer' will exit the processing loop when paused -} -void ILibDuktape_TlsStream_Encrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - ILibDuktape_TlsStream_ProcessEncryptedBuffer(data); -} -int ILibDuktape_TlsStream_Encrypted_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user) -{ - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user; - - if (unshiftBytes == data->writeBioBuffer->length) - { - data->encrypted_unshiftBytes = -1; - } - else - { - data->writeBioBuffer->data += ((int)data->writeBioBuffer->length - unshiftBytes); - data->writeBioBuffer->length = unshiftBytes; - } - return(unshiftBytes); -} -int ILibDuktape_TlsStream_verify(int preverify_ok, X509_STORE_CTX *ctx) -{ - STACK_OF(X509) *certChain = X509_STORE_CTX_get_chain(ctx); - SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(ssl, ILibDuktape_TlsStream_ctx2stream); - - int i; - int retVal = 0; - - if (data->rejectUnauthorized != 0) { return(preverify_ok); } - if (data->OnVerify == NULL) { return 1; } - - duk_push_heapptr(data->ctx, data->OnVerify); // [func] - duk_push_heapptr(data->ctx, data->emitter->object); // [func][this] - duk_push_array(data->ctx); // [func][this][certs] - for (i = 0; i < sk_X509_num(certChain); ++i) - { - ILibDuktape_TlsStream_X509_PUSH(data->ctx, sk_X509_value(certChain, i)); // [func][this][certs][cert] - duk_put_prop_index(data->ctx, -2, i); // [func][this][certs] - } - retVal = duk_pcall_method(data->ctx, 1) == 0 ? 1 : 0; // [undefined] - duk_pop(data->ctx); // ... - return retVal; -} -duk_ret_t ILibDuktape_TlsStream_Finalizer(duk_context *ctx) -{ - void *chain = Duktape_GetChain(ctx); - duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream_Ptr); - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL); - struct util_cert *cert = NULL; - - if (data->ssl != NULL) { SSL_free(data->ssl); } - if (data->ssl_ctx != NULL) { SSL_CTX_free(data->ssl_ctx); } - if (data->decryptedBuffer != NULL) { free(data->decryptedBuffer); } - - if (duk_has_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert)) - { - duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert); - cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL); - util_freecert(cert); - } - ILibDuktape_InValidatePointer(chain, data); - return(0); -} -duk_ret_t ILibDuktape_TlsStream_serverSNI_cb(duk_context *ctx) -{ - duk_push_current_function(ctx); - duk_get_prop_string(ctx, -1, "\xFF_ptr"); - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)duk_get_pointer(ctx, -1); - - if (duk_has_prop_string(ctx, 1, "pfx") && duk_has_prop_string(ctx, 1, "passphrase")) - { - char *passphrase = Duktape_GetStringPropertyValue(ctx, 1, "passphrase", ""); - char *pfx; - duk_size_t pfxLen; - duk_get_prop_string(ctx, 1, "pfx"); - pfx = (char*)Duktape_GetBuffer(ctx, -1, &pfxLen); - duk_push_heapptr(ctx, data->tlsObject); // [TLS] - duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][cert] - struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL); - - if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); } - SSL_CTX *newCTX = SSL_CTX_new(SSLv23_server_method()); - SSL_CTX_set_options(newCTX, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); - SSL_CTX_set_verify(newCTX, SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */ - SSL_CTX_use_certificate(newCTX, cert->x509); - SSL_CTX_use_PrivateKey(newCTX, cert->pkey); - - SSL_set_SSL_CTX(data->ssl, newCTX); - - duk_get_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS][cert][oldCert] - util_freecert((struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL)); - duk_pop(ctx); // [TLS][cert] - duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS] - SSL_CTX_free(data->ssl_ctx); - data->ssl_ctx = newCTX; - } - - return(0); -} -static int ILibDuktape_TlsStream_serverSNI_callback(SSL *s, int *ad, void *arg) -{ - const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); - ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(s, ILibDuktape_TlsStream_ctx2stream); - int retVal = SSL_TLSEXT_ERR_OK; - - duk_push_heapptr(data->ctx, data->OnServerSNI); // [func] - duk_push_heapptr(data->ctx, data->tlsObject); // [func][this] - duk_push_string(data->ctx, servername); // [func][this][servername] - duk_push_c_function(data->ctx, ILibDuktape_TlsStream_serverSNI_cb, 2); // [func][this][servername][cb] - duk_push_pointer(data->ctx, data); // [func][this][servername][cb][ptr] - duk_put_prop_string(data->ctx, -2, "\xFF_ptr"); // [func][this][servername][cb] - if (duk_pcall_method(data->ctx, 2) != 0) - { - ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.serverSNI(): Error dispatching callback "); - retVal = SSL_TLSEXT_ERR_NOACK; - } - duk_pop(data->ctx); // ... - - return(retVal); -} -duk_ret_t ILibDuktape_TlsStream_create(duk_context *ctx) -{ - int nargs = duk_get_top(ctx); - char *sniHost = NULL; - void *chain = Duktape_GetChain(ctx); - int status, requestCert; - duk_push_current_function(ctx); - int isClient = Duktape_GetIntPropertyValue(ctx, -1, "isClient", 0); - ILibDuktape_TlsStream_Data *data; - duk_push_object(ctx); // [TLS] - ILibDuktape_CreateFinalizer(ctx, ILibDuktape_TlsStream_Finalizer); - duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_TlsStream_Data)); // [TLS][struct] - data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL); - duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream_Ptr); // [TLS] - memset(data, 0, sizeof(ILibDuktape_TlsStream_Data)); - ILibDuktape_ValidatePointer(chain, data); - data->emitter = ILibDuktape_EventEmitter_Create(ctx); - ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "connect"); - data->tlsObject = duk_get_heapptr(ctx, -1); - data->decryptedBuffer_mallocSize = MEMORYCHUNKSIZE; - data->decryptedBuffer = (char*)ILibMemory_Allocate(data->decryptedBuffer_mallocSize, 0, NULL, NULL); - - data->rejectUnauthorized = Duktape_GetIntPropertyValue(ctx, 0, "rejectUnauthorized", 1); - requestCert = Duktape_GetIntPropertyValue(ctx, 0, "requestCert", 0); - data->OnVerify = Duktape_GetHeapptrProperty(ctx, 0, isClient != 0 ? "checkServerIdentity" : "checkClientIdentity"); - - duk_push_object(ctx); // [TLS][clear] - ILibDuktape_WriteID(ctx, "TlsStream.decrypted"); - data->clear = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Clear_WriteSink, ILibDuktape_TlsStream_Clear_EndSink, - ILibDuktape_TlsStream_Clear_PauseSink, ILibDuktape_TlsStream_Clear_ResumeSink, ILibDuktape_TlsStream_Clear_UnshiftSink, data); - ILibDuktape_CreateReadonlyProperty(ctx, "clear"); // [TLS] - - duk_push_object(ctx); // [TLS][encrypted] - ILibDuktape_WriteID(ctx, "TlsStream.encrypted"); - data->encrypted = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Encrypted_WriteSink, ILibDuktape_TlsStream_Encrypted_EndSink, - ILibDuktape_TlsStream_Encrypted_PauseSink, ILibDuktape_TlsStream_Encrypted_ResumeSink, ILibDuktape_TlsStream_Encrypted_UnshiftSink, data); - ILibDuktape_CreateReadonlyProperty(ctx, "encrypted"); // [TLS] - - - data->ctx = ctx; - data->chain = Duktape_GetChain(ctx); - data->ssl_ctx = isClient != 0 ? SSL_CTX_new(SSLv23_client_method()) : SSL_CTX_new(SSLv23_server_method()); - SSL_CTX_set_options(data->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); - if (isClient != 0 || requestCert != 0) { SSL_CTX_set_verify(data->ssl_ctx, isClient != 0 ? SSL_VERIFY_PEER : SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */ } - - if (nargs > 0 && duk_is_object(ctx, 0)) - { - sniHost = Duktape_GetStringPropertyValue(ctx, 0, "host", NULL); - data->OnServerSNI = Duktape_GetHeapptrProperty(ctx, 0, "SNICallback"); - if (duk_has_prop_string(ctx, 0, "pfx") && duk_has_prop_string(ctx, 0, "passphrase")) - { - // PFX certificate was passed in thru Options - char *pfx, *passphrase; - duk_size_t pfxLen, passphraseLen; - duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][buff] - struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL); - duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS] - - duk_get_prop_string(ctx, 0, "pfx"); // [pfx] - duk_get_prop_string(ctx, 0, "passphrase"); // [pfx][passphrase] - pfx = (char*)Duktape_GetBuffer(ctx, -2, &pfxLen); - passphrase = (char*)Duktape_GetBuffer(ctx, -1, &passphraseLen); - - if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); } - SSL_CTX_use_certificate(data->ssl_ctx, cert->x509); - SSL_CTX_use_PrivateKey(data->ssl_ctx, cert->pkey); - duk_pop_2(ctx); - } - } - - data->ssl = SSL_new(data->ssl_ctx); - data->TLSHandshakeCompleted = 0; - data->readBio = BIO_new(BIO_s_mem()); - data->writeBio = BIO_new(BIO_s_mem()); - BIO_get_mem_ptr(data->readBio, &(data->readBioBuffer)); - BIO_get_mem_ptr(data->writeBio, &(data->writeBioBuffer)); - BIO_set_mem_eof_return(data->readBio, -1); - BIO_set_mem_eof_return(data->writeBio, -1); - data->readBioBuffer->length = 0; - SSL_set_bio(data->ssl, data->readBio, data->writeBio); - - if (ILibDuktape_TlsStream_ctx2stream < 0) - { - ILibDuktape_TlsStream_ctx2stream = SSL_get_ex_new_index(0, "ILibDuktape_TlsStream index", NULL, NULL, NULL); - } - SSL_set_ex_data(data->ssl, ILibDuktape_TlsStream_ctx2stream, data); - - if (isClient != 0) - { - if (sniHost != NULL) { SSL_set_tlsext_host_name(data->ssl, sniHost); } - SSL_set_connect_state(data->ssl); - status = SSL_do_handshake(data->ssl); - if (status <= 0) { status = SSL_get_error(data->ssl, status); } - if (status == SSL_ERROR_WANT_READ) - { - ILibDuktape_TlsStream_ProcessEncryptedBuffer(data); - // We're going to drop out now, becuase we need to check for received data - } - } - else - { - if (data->OnServerSNI != NULL) - { - SSL_CTX_set_tlsext_servername_callback(data->ssl_ctx, ILibDuktape_TlsStream_serverSNI_callback); - } - SSL_set_accept_state(data->ssl); // Setup server SSL state - } - - return(1); -} - -void ILibDuktape_TlsStream_PUSH(duk_context *ctx, void *chain) -{ - duk_push_object(ctx); - ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 1, "createClient", ILibDuktape_TlsStream_create, DUK_VARARGS); - ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 0, "createServer", ILibDuktape_TlsStream_create, DUK_VARARGS); -} -void ILibDuktape_TlsStream_Init(duk_context *ctx) -{ - ILibDuktape_ModSearch_AddHandler(ctx, "TlsStream", ILibDuktape_TlsStream_PUSH); -} -