Trivial TLS client

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Here's a trivial TLS client program for testing this.

David
---
/*
 * TLS-over-TCP send client
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <linux/tls.h>

#define OSERROR(X, Y) do { if ((long)(X) == -1) { perror(Y); exit(1); } } while(0)

static unsigned char buffer[4096] __attribute__((aligned(4096)));

static void set_tls(int sock)
{
	struct tls12_crypto_info_aes_gcm_128 crypto_info;

	crypto_info.info.version = TLS_1_2_VERSION;
	crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
	memset(crypto_info.iv,		0, TLS_CIPHER_AES_GCM_128_IV_SIZE);
	memset(crypto_info.rec_seq,	0, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
	memset(crypto_info.key,		0, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
	memset(crypto_info.salt,	0, TLS_CIPHER_AES_GCM_128_SALT_SIZE);

	OSERROR(setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")),
		"TCP_ULP");
	OSERROR(setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)),
		"TLS_TX");
	OSERROR(setsockopt(sock, SOL_TLS, TLS_RX, &crypto_info, sizeof(crypto_info)),
		"TLS_RX");
}

int main(int argc, char *argv[])
{
	struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = htons(5556) };
	struct hostent *h;
	struct stat st;
	ssize_t r, o;
	int sf = 0;
	int cfd, fd;

	if (argc > 1 && strcmp(argv[1], "-s") == 0) {
		sf = 1;
		argc--;
		argv++;
	}
	
	if (argc != 3) {
		fprintf(stderr, "tcp-send [-s] <server> <file>\n");
		exit(2);
	}

	h = gethostbyname(argv[1]);
	if (!h) {
		fprintf(stderr, "%s: %s\n", argv[1], hstrerror(h_errno));
		exit(3);
	}

	if (!h->h_addr_list[0]) {
		fprintf(stderr, "%s: No addresses\n", argv[1]);
		exit(3);
	}

	memcpy(&sin.sin_addr, h->h_addr_list[0], h->h_length);
	
	cfd = socket(AF_INET, SOCK_STREAM, 0);
	OSERROR(cfd, "socket");
	OSERROR(connect(cfd, (struct sockaddr *)&sin, sizeof(sin)), "connect");
	set_tls(cfd);

	fd = open(argv[2], O_RDONLY);
	OSERROR(fd, argv[2]);
	OSERROR(fstat(fd, &st), argv[2]);

	if (!sf) {
		for (;;) {
			r = read(fd, buffer, sizeof(buffer));
			OSERROR(r, argv[2]);
			if (r == 0)
				break;

			o = 0;
			do {
				ssize_t w = write(cfd, buffer + o, r - o);
				OSERROR(w, "write");
				o += w;
			} while (o < r);
		}
	} else {
		off_t off = 0;
		r = sendfile(cfd, fd, &off, st.st_size);
		OSERROR(r, "sendfile");
		if (r != st.st_size) {
			fprintf(stderr, "Short sendfile\n");
			exit(1);
		}
	}

	OSERROR(close(cfd), "close/c");
	OSERROR(close(fd), "close/f");
	return 0;
}





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux