ssl_server_client * ssl_server_listen(ssl_server * serv){ BIO * bio = BIO_new_dgram(serv->fd, BIO_NOCLOSE); { struct timeval timeout; timeout.tv_sec = 10; timeout.tv_usec = 0; BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); } SSL * ssl = SSL_new(serv->ctx); SSL_set_bio(ssl, bio, bio); SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); struct sockaddr_storage client_addr; while (DTLSv1_listen(ssl, &client_addr) <= 0){ SSL_free(ssl); return NULL; } ssl_server_client * con = alloc0(sizeof(ssl_server_client)); con->ssl = ssl; con->addr = client_addr; con->bio = bio; return con; }
int main(void) { SSL_CTX *ctx = NULL; SSL *ssl = NULL; BIO *outbio = NULL; BIO *inbio = NULL; BIO_ADDR *peer = BIO_ADDR_new(); char *data; long datalen; int ret, success = 0; size_t i; ctx = SSL_CTX_new(DTLS_server_method()); if (ctx == NULL || peer == NULL) goto err; SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen); SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify); /* Create an SSL object for the connection */ ssl = SSL_new(ctx); if (ssl == NULL) goto err; outbio = BIO_new(BIO_s_mem()); if (outbio == NULL) goto err; SSL_set_wbio(ssl, outbio); success = 1; for (i = 0; i < OSSL_NELEM(testpackets) && success; i++) { inbio = BIO_new_mem_buf((char *)testpackets[i].in, testpackets[i].inlen); if (inbio == NULL) { success = 0; goto err; } /* Set Non-blocking IO behaviour */ BIO_set_mem_eof_return(inbio, -1); SSL_set_rbio(ssl, inbio); /* Process the incoming packet */ ret = DTLSv1_listen(ssl, peer); if (ret < 0) { success = 0; goto err; } datalen = BIO_get_mem_data(outbio, &data); if (testpackets[i].outtype == VERIFY) { if (ret == 0) { if (datalen != sizeof(verify) || (memcmp(data, verify, sizeof(verify)) != 0)) { printf("Test %ld failure: incorrect HelloVerifyRequest\n", i); success = 0; } else { printf("Test %ld success\n", i); } } else { printf ("Test %ld failure: should not have succeeded\n", i); success = 0; } } else if (datalen == 0) { if ((ret == 0 && testpackets[i].outtype == DROP) || (ret == 1 && testpackets[i].outtype == GOOD)) { printf("Test %ld success\n", i); } else { printf("Test %ld failure: wrong return value\n", i); success = 0; } } else { printf("Test %ld failure: Unexpected data output\n", i); success = 0; } (void)BIO_reset(outbio); inbio = NULL; /* Frees up inbio */ SSL_set_rbio(ssl, NULL); } err: if (!success) ERR_print_errors_fp(stderr); /* Also frees up outbio */ SSL_free(ssl); SSL_CTX_free(ctx); BIO_free(inbio); OPENSSL_free(peer); #ifndef OPENSSL_NO_CRYPTO_MDEBUG CRYPTO_mem_leaks_fp(stderr); #endif return success ? 0 : 1; }
void DataPlaneServer::readyRead(int) { memset(&client_addr, 0, sizeof(struct sockaddr_storage)); /* Create BIO */ bio = BIO_new_dgram(fd, BIO_NOCLOSE); /* Set and activate timeouts */ timeout.tv_sec = 5; timeout.tv_usec = 0; BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); ssl = SSL_new(ctx); SSL_set_bio(ssl, bio, bio); SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); int dtlsRet; errno = 0; while ((dtlsRet = DTLSv1_listen(ssl, &client_addr)) <= 0) { if (errno != EAGAIN) { qWarning() << "DTLSv1_listen error"; qWarning() << SSL_get_error(ssl, dtlsRet); qWarning() << "Errno is" << errno; if (errno == EINVAL) { qWarning() << "!!!!!!!!!!! Your openssl library does not support DTLSv1_listen !!!!!!!!!!!"; qWarning() << "Cannot accept new connection"; SSL_shutdown(ssl); close(fd); SSL_free(ssl); ERR_remove_state(0); return; } } } QThread* workerThread = new QThread(); threads.append(workerThread); addrUnion infServer_addr; addrUnion infClient_addr; memcpy(&infServer_addr, &server_addr, sizeof(struct sockaddr_storage)); memcpy(&infClient_addr, &client_addr, sizeof(struct sockaddr_storage)); // get UID from friend using his IP to create worker thread // if IP is not in DB we close the connection char friendIp[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &infClient_addr.s6.sin6_addr, friendIp, INET6_ADDRSTRLEN); ConnectionInitiator* init = ConnectionInitiator::getInstance(); QString friendUid = qSql->getUidFromIP(QHostAddress(QString(friendIp))); ControlPlaneConnection* cp = init->getConnection(friendUid); if (friendUid.isEmpty() || cp->getMode() == Closed) { qDebug() << "friendUId NOT in DB or no control plane connection!"; SSL_shutdown(ssl); close(fd); //free(info); SSL_free(ssl); ERR_remove_state(0); qDebug("done, connection closed."); fflush(stdout); return; } // associate with dataplaneconnection DataPlaneConnection* dpc = init->getDpConnection(friendUid); ServerWorker* worker = new ServerWorker(infServer_addr, infClient_addr, ssl, dpc); worker->moveToThread(workerThread); connect(workerThread, SIGNAL(started()), worker, SLOT(connection_handle())); connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); //connect(worker, SIGNAL(bufferReady(const char*, int)), dpc, SLOT(readBuffer(const char*, int))); UnixSignalHandler* u = UnixSignalHandler::getInstance(); connect(u, SIGNAL(exiting()), workerThread, SLOT(quit())); workerThread->start(); }