tnet_dtls_socket_handle_t* tnet_dtls_socket_create(struct tnet_socket_s* wrapped_sock, struct ssl_ctx_st* ssl_ctx) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); return tsk_null; #else tnet_dtls_socket_t* socket; if (!wrapped_sock || !ssl_ctx){ TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) { const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP socket->wrapped_sock = tsk_object_ref(wrapped_sock); if (!(socket->ssl = SSL_new(ssl_ctx))) { TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); TSK_OBJECT_SAFE_FREE(socket); return tsk_null; } if (set_mtu) { SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28); socket->ssl->d1->mtu = TNET_DTLS_MTU - 28; } if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))){ TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null)); if (socket->rbio){ BIO_free(socket->rbio); } if (socket->wbio){ BIO_free(socket->wbio); } TSK_OBJECT_SAFE_FREE(socket); return tsk_null; } BIO_set_mem_eof_return(socket->rbio, -1); BIO_set_mem_eof_return(socket->wbio, -1); SSL_set_bio(socket->ssl, socket->rbio, socket->wbio); SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY); SSL_set_read_ahead(socket->ssl, 1); if (set_mtu) { BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL); } if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))){ TSK_DEBUG_INFO("SSL cert verify: ON"); socket->verify_peer = tsk_true; SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert); } else { TSK_DEBUG_ERROR("Verity not enabled"); } SSL_set_app_data(socket->ssl, socket); } return socket; #endif }
CWBool CWSecurityInitSessionClient(CWSocket sock, CWNetworkLev4Address *addrPtr, CWSafeList packetReceiveList, CWSecurityContext ctx, CWSecuritySession *sessionPtr, int *PMTUPtr) { BIO *sbio = NULL; CWNetworkLev4Address peer; int peerlen = sizeof(peer); int i; if(ctx == NULL || sessionPtr == NULL || PMTUPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); if((*sessionPtr = SSL_new(ctx)) == NULL) { CWSecurityRaiseError(CW_ERROR_CREATING); } #ifdef CW_DEBUGGING CWDebugLog("My Certificate"); PEM_write_X509(stdout, SSL_get_certificate(*sessionPtr)); #endif if((sbio = BIO_new_memory(sock, addrPtr, packetReceiveList)) == NULL) { SSL_free(*sessionPtr); CWSecurityRaiseError(CW_ERROR_CREATING); } if (getsockname(sock, (struct sockaddr*)&peer, (void *)&peerlen) < 0) { SSL_free(*sessionPtr); CWSecurityRaiseSystemError(CW_ERROR_GENERAL); } i = BIO_ctrl_set_connected(sbio, 1, &peer); //BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); // TO-DO (pass MTU?) BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 10000, NULL); // TO-DO if we don't set a big MTU, thw DTLS implementation will // not be able to use a big certificate // Let the verify_callback catch the verify_depth error so that we get // an appropriate error in the logfile. SSL_set_verify_depth((*sessionPtr), CW_DTLS_CERT_VERIFY_DEPTH + 1); SSL_set_read_ahead( (*sessionPtr), 1); // required by DTLS implementation to avoid data loss SSL_set_bio((*sessionPtr), sbio, sbio); SSL_set_connect_state((*sessionPtr)); CWDebugLog("Before HS"); CWSecurityManageSSLError( SSL_do_handshake(*sessionPtr), *sessionPtr, SSL_free(*sessionPtr););
/****************************************************************************** ****************************************************************************** ** Common Routines for lcbio_TABLE Emulation ** ****************************************************************************** ******************************************************************************/ void iotssl_init_common(lcbio_XSSL *xs, lcbio_TABLE *orig, SSL_CTX *sctx) { lcbio_TABLE *base = &xs->base_; xs->iops_dummy_ = calloc(1, sizeof(*xs->iops_dummy_)); xs->iops_dummy_->v.v0.cookie = xs; xs->orig = orig; base->model = xs->orig->model; base->p = xs->iops_dummy_; base->refcount = 1; base->loop.start = loop_run; base->loop.stop = loop_stop; base->timer.create = create_timer; base->timer.destroy = destroy_timer; base->timer.schedule = schedule_timer; base->timer.cancel = cancel_timer; if (orig->model == LCB_IOMODEL_EVENT) { base->u_io.v0.ev.create = create_event; base->u_io.v0.ev.destroy = destroy_event; base->u_io.v0.io.is_closed = Eis_closed; } else { base->u_io.completion.is_closed = Cis_closed; } lcbio_table_ref(xs->orig); xs->error = 0; xs->ssl = SSL_new(sctx); xs->rbio = BIO_new(BIO_s_mem()); xs->wbio = BIO_new(BIO_s_mem()); SSL_set_bio(xs->ssl, xs->rbio, xs->wbio); SSL_set_read_ahead(xs->ssl, 0); /* Indicate that we are a client */ SSL_set_connect_state(xs->ssl); }
int dtls_netsock_init(const STREAM_DTLS_CTXT_T *pDtlsCtxt, NETIO_SOCK_T *pnetsock, const DTLS_FINGERPRINT_VERIFY_T *pFingerprintVerify, const DTLS_KEY_UPDATE_CTXT_T *pKeysUpdateCtxt) { int rc = 0; if(!pDtlsCtxt || !pnetsock) { return -1; } if(!pnetsock || PNETIOSOCK_FD(pnetsock) == INVALID_SOCKET) { return -1; } pthread_mutex_lock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx); if(pDtlsCtxt->active != 1) { pthread_mutex_unlock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx); return -1; } if(!(pnetsock->ssl.pCtxt = SSL_new(pDtlsCtxt->pctx))) { LOG(X_ERROR("DTLS SSL_new failed: %s"), ERR_reason_error_string(ERR_get_error())); rc = -1; } pnetsock->ssl.ownCtxt = 1; if(rc >= 0 && !(pnetsock->ssl.pBioRd = BIO_new(BIO_s_mem()))) { LOG(X_ERROR("DTLS BIO_new (reader) failed: %s"), ERR_reason_error_string(ERR_get_error())); rc = -1; } pnetsock->ssl.ownBioRd = 1; if(rc >= 0 && !(pnetsock->ssl.pBioWr = BIO_new(BIO_s_mem()))) { LOG(X_ERROR("DTLS BIO_new (writer) failed: %s"), ERR_reason_error_string(ERR_get_error())); rc = -1; } pnetsock->ssl.ownBioWr = 1; if(rc >= 0) { BIO_set_mem_eof_return(pnetsock->ssl.pBioRd, -1); BIO_set_mem_eof_return(pnetsock->ssl.pBioWr, -1); SSL_set_bio(pnetsock->ssl.pCtxt, pnetsock->ssl.pBioRd, pnetsock->ssl.pBioWr); pnetsock->ssl.ownBioRd = 0; pnetsock->ssl.ownBioWr = 0; SSL_set_mode(pnetsock->ssl.pCtxt, SSL_MODE_AUTO_RETRY); SSL_set_read_ahead(pnetsock->ssl.pCtxt, 1); //SSL_set_connect_state(pnetsock->ssl.pCtxt); //SSL_set_accept_state(pnetsock->ssl.pCtxt); if(pFingerprintVerify) { if(s_sslCbDataIndex == -1) { s_sslCbDataIndex = SSL_get_ex_new_index(0, "verifycbIndex", NULL, NULL, NULL); } SSL_set_verify(pnetsock->ssl.pCtxt, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), dtls_verify_cb); SSL_set_ex_data(pnetsock->ssl.pCtxt, s_sslCbDataIndex, (void *) pFingerprintVerify); //LOG(X_DEBUG("SSL_set_ex_data index:%d, pFingerprintVerify: 0x%x"), s_sslCbDataIndex, pFingerprintVerify); } } pnetsock->ssl.pDtlsCtxt = pDtlsCtxt; pnetsock->flags |= NETIO_FLAG_SSL_DTLS; if(pDtlsCtxt->dtls_srtp) { pnetsock->flags |= NETIO_FLAG_SRTP; if(pKeysUpdateCtxt) { memcpy(&pnetsock->ssl.dtlsKeysUpdateCtxt, pKeysUpdateCtxt, sizeof(pnetsock->ssl.dtlsKeysUpdateCtxt)); } } pthread_mutex_unlock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx); return rc; }
/* Switch on a filedescriptor */ int ggz_tls_enable_fd(int fd, GGZTLSType mode, GGZTLSVerificationType verify) { int ret, ret2; STACK_OF(SSL_CIPHER) *stack; SSL_CIPHER *cipher; int bits; char *cipherlist; SSL *_tls; int _tls_active; struct list_entry *entry; _state = 1; _tls_active = 0; if((mode != GGZ_TLS_CLIENT) && (mode != GGZ_TLS_SERVER)) { TLSERROR("Wrong mode."); return 0; } if(!_tlsctx) tls_init(verify); _tls = SSL_new(_tlsctx); if(_tls) { cipherlist = NULL; stack = SSL_get_ciphers(_tls); while((cipher = (SSL_CIPHER*)sk_pop(stack)) != NULL) { printf("* Cipher: %s\n", SSL_CIPHER_get_name(cipher)); printf(" Bits: %i\n", SSL_CIPHER_get_bits(cipher, &bits)); printf(" Used bits: %i\n", bits); printf(" Version: %s\n", SSL_CIPHER_get_version(cipher)); printf(" Description: %s\n", SSL_CIPHER_description(cipher, NULL, 0)); if(cipherlist) { cipherlist = (char*)realloc(cipherlist, (strlen(cipherlist) + 1) + strlen(SSL_CIPHER_get_name(cipher)) + 1); strcat(cipherlist, ":"); strcat(cipherlist, SSL_CIPHER_get_name(cipher)); } else { cipherlist = (char*)malloc(strlen(SSL_CIPHER_get_name(cipher)) + 1); strcpy(cipherlist, SSL_CIPHER_get_name(cipher)); } } printf("Available ciphers: %s\n", cipherlist); ret = SSL_set_cipher_list(_tls, cipherlist); if(!ret) TLSERROR("Cipher selection failed."); ret = SSL_set_fd(_tls, fd); if(!ret) TLSERROR("Assignment to connection failed."); else { SSL_set_read_ahead(_tls, 1); if(mode == GGZ_TLS_SERVER) { tls_certkey(_tls); if(_state) { SSL_set_accept_state(_tls); ret = SSL_accept(_tls); } } else { SSL_set_connect_state(_tls); ret = SSL_connect(_tls); } if((ret != 1) || (!_state)) { printf("Ret: %i, State: %i\n", ret, _state); TLSERROR("Handshake failed."); ret2 = ERR_get_error(); printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL), ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2)); } else { printf(">>>>> Handshake successful.\n"); if((mode == GGZ_TLS_SERVER) || (verify == GGZ_TLS_VERIFY_NONE)) _tls_active = 1; else { printf(">>>>> Client side, thus checking Certificate.\n"); printf("Negotiated cipher: %s\n", SSL_get_cipher(_tls)); printf("Shared ciphers: %s\n", SSL_get_shared_ciphers(_tls, NULL, 0)); if(SSL_get_peer_certificate(_tls)) { if(SSL_get_verify_result(_tls) == X509_V_OK) { _tls_active = 1; } else { printf("Error code: %li\n", SSL_get_verify_result(_tls)); TLSERROR("Invalid certificate, or certificate is not self-signed."); } } else TLSERROR("Couldn't get certificate."); } } entry = (struct list_entry*)ggz_malloc(sizeof(struct list_entry)); entry->tls = _tls; entry->fd = fd; entry->active = _tls_active; ggz_list_insert(openssllist, entry); return 1; } } return 0; }
static int openssl_ssl_set(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); int ret = 1; for (i = 2; i <= top; i += 2) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { ret = SSL_set_fd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "rfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "wfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "client_CA") == 0) { X509* x = CHECK_OBJECT(i + 1, X509, "openssl.x509"); ret = SSL_add_client_CA(s, x); } else if (strcmp(what, "read_ahead") == 0) { int yes = auxiliar_checkboolean(L, i + 1); SSL_set_read_ahead(s, yes); } else if (strcmp(what, "cipher_list") == 0) { const char* list = lua_tostring(L, i + 1); ret = SSL_set_cipher_list(s, list); } else if (strcmp(what, "verify_depth") == 0) { int depth = luaL_checkint(L, i + 1); SSL_set_verify_depth(s, depth); } else if (strcmp(what, "purpose") == 0) { //FIX int purpose = luaL_checkint(L, i + 1); ret = SSL_set_purpose(s, purpose); } else if (strcmp(what, "trust") == 0) { //FIX int trust = luaL_checkint(L, i + 1); ret = SSL_set_trust(s, trust); } else if (strcmp(what, "verify_result") == 0) { int result = luaL_checkint(L, i + 1); SSL_set_verify_result(s, result); } else if (strcmp(what, "hostname") == 0) { const char* hostname = luaL_checkstring(L, i + 1); SSL_set_tlsext_host_name(s, hostname); } #if OPENSSL_VERSION_NUMBER > 0x10000000L else if (strcmp(what, "state") == 0) { int l = luaL_checkint(L, 2); SSL_set_state(s, l); } #endif else luaL_argerror(L, i, "don't understand"); if (ret != 1) return openssl_pushresult(L, ret); } return 0; }