Skip to content

Instantly share code, notes, and snippets.

@yossigo
Created July 4, 2019 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yossigo/09b530bbde96cb70153aa1dc78abc935 to your computer and use it in GitHub Desktop.
Save yossigo/09b530bbde96cb70153aa1dc78abc935 to your computer and use it in GitHub Desktop.
A small client that tests TLS renegotiation in the middle of sending a Redis command.
/* A small test client that:
* 1. Establishes a TLS connection with Redis.
* 2. Starts sending a request, getting Redis to read it.
* 3. Before completing the command, initiates renegotiation.
*
* This basically aims to test the ability of the TLS implementation
* to respond while busy in an SSL_read() type of operation.
*/
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
int make_socket(const char *addr, int port)
{
struct hostent *host;
struct sockaddr_in sa;
int fd;
int ret;
host = gethostbyname(addr);
assert(host != NULL);
fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = ntohs(port);
sa.sin_addr.s_addr = *(long *)(host->h_addr);
ret = connect(fd, (struct sockaddr *) &sa, sizeof(struct sockaddr));
assert(ret != -1);
return fd;
}
void start_request(SSL *ssl)
{
const char request[] = "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$10000\r\n";
int ret = SSL_write(ssl, request, strlen(request));
assert(ret == strlen(request));
fprintf(stderr, ">> Started a request\n");
}
void complete_request(SSL *ssl)
{
char data[10002] = { 0 };
int ret;
data[10000] = '\r';
data[10001] = '\n';
ret = SSL_write(ssl, data, sizeof(data));
assert(ret == sizeof(data));
fprintf(stderr, ">> Completed request, reading response...\n");
char resp[100];
ret = SSL_read(ssl, resp, 100);
assert(ret > 0);
fprintf(stderr, " Received:\n%.*s\n", ret, resp);
}
int main() {
/* Initialize */
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
SSL_library_init();
/* Prepare client and context */
const SSL_METHOD *method;
SSL_CTX *ctx;
SSL *ssl;
int sock;
int ret;
method = TLS_client_method();
ctx = SSL_CTX_new(method);
assert(ctx != NULL);
/* New connection */
ssl = SSL_new(ctx);
sock = make_socket("127.0.0.1", 6379);
assert(sock != -1);
SSL_set_fd(ssl, sock);
ret = SSL_connect(ssl);
assert(ret == 1);
fprintf(stderr, ">> TLS connection establishd.\n");
/* Run a few request/responses */
int i;
for (i = 0; i < 10; i++) {
start_request(ssl);
complete_request(ssl);
}
/* Start another request */
start_request(ssl);
/* Now request renegotiation;
*
* NOTE -- on TLS 1.3 this will fail and should use SSL_key_update()
* instead.
*/
ret = SSL_renegotiate(ssl);
assert(ret == 1);
/* Now try to complete the request */
complete_request(ssl);
fprintf(stderr, "All done.\n");
SSL_free(ssl);
close(sock);
SSL_CTX_free(ctx);
return(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment