245 lines
4.9 KiB
C
245 lines
4.9 KiB
C
|
/* test.c */
|
||
|
/* $Id: test.c,v 1.1 2001/09/17 19:06:59 bodo Exp $ */
|
||
|
|
||
|
#define L_PORT 9999
|
||
|
#define C_PORT 443
|
||
|
|
||
|
#include <arpa/inet.h>
|
||
|
#include <assert.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <netinet/tcp.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/select.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "test.h"
|
||
|
#include "easy-tls.h"
|
||
|
|
||
|
void
|
||
|
test_process_init(int fd, int client_p, void *apparg)
|
||
|
{
|
||
|
fprintf(stderr, "test_process_init(fd = %d, client_p = %d, apparg = %p)\n", fd, client_p, apparg);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
test_errflush(int child_p, char *errbuf, size_t num, void *apparg)
|
||
|
{
|
||
|
fputs(errbuf, stderr);
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
main(int argc, char *argv[])
|
||
|
{
|
||
|
int s, fd, r;
|
||
|
FILE *conn_in;
|
||
|
FILE *conn_out;
|
||
|
char buf[256];
|
||
|
SSL_CTX *ctx;
|
||
|
int client_p = 0;
|
||
|
int port;
|
||
|
int tls = 0;
|
||
|
char infobuf[TLS_INFO_SIZE + 1];
|
||
|
|
||
|
if (argc > 1 && argv[1][0] == '-') {
|
||
|
fputs("Usage: test [port] -- server\n"
|
||
|
" test num.num.num.num [port] -- client\n",
|
||
|
stderr);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (argc > 1) {
|
||
|
if (strchr(argv[1], '.')) {
|
||
|
client_p = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fputs(client_p ? "Client\n" : "Server\n", stderr);
|
||
|
|
||
|
{
|
||
|
struct tls_create_ctx_args a = tls_create_ctx_defaultargs();
|
||
|
a.client_p = client_p;
|
||
|
a.certificate_file = "cert.pem";
|
||
|
a.key_file = "cert.pem";
|
||
|
a.ca_file = "cacerts.pem";
|
||
|
|
||
|
ctx = tls_create_ctx(a, NULL);
|
||
|
if (ctx == NULL)
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
if (s == -1) {
|
||
|
perror("socket");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (client_p) {
|
||
|
struct sockaddr_in addr;
|
||
|
size_t addr_len = sizeof addr;
|
||
|
|
||
|
addr.sin_family = AF_INET;
|
||
|
assert(argc > 1);
|
||
|
if (argc > 2)
|
||
|
sscanf(argv[2], "%d", &port);
|
||
|
else
|
||
|
port = C_PORT;
|
||
|
addr.sin_port = htons(port);
|
||
|
addr.sin_addr.s_addr = inet_addr(argv[1]);
|
||
|
|
||
|
r = connect(s, &addr, addr_len);
|
||
|
if (r != 0) {
|
||
|
perror("connect");
|
||
|
exit(1);
|
||
|
}
|
||
|
fd = s;
|
||
|
fprintf(stderr, "Connect (fd = %d).\n", fd);
|
||
|
} else {
|
||
|
/* server */
|
||
|
{
|
||
|
int i = 1;
|
||
|
|
||
|
r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof i);
|
||
|
if (r == -1) {
|
||
|
perror("setsockopt");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
struct sockaddr_in addr;
|
||
|
size_t addr_len = sizeof addr;
|
||
|
|
||
|
if (argc > 1)
|
||
|
sscanf(argv[1], "%d", &port);
|
||
|
else
|
||
|
port = L_PORT;
|
||
|
addr.sin_family = AF_INET;
|
||
|
addr.sin_port = htons(port);
|
||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||
|
|
||
|
r = bind(s, &addr, addr_len);
|
||
|
if (r != 0) {
|
||
|
perror("bind");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
r = listen(s, 1);
|
||
|
if (r == -1) {
|
||
|
perror("listen");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
fprintf(stderr, "Listening at port %i.\n", port);
|
||
|
|
||
|
fd = accept(s, NULL, 0);
|
||
|
if (fd == -1) {
|
||
|
perror("accept");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
fprintf(stderr, "Accept (fd = %d).\n", fd);
|
||
|
}
|
||
|
|
||
|
conn_in = fdopen(fd, "r");
|
||
|
if (conn_in == NULL) {
|
||
|
perror("fdopen");
|
||
|
exit(1);
|
||
|
}
|
||
|
conn_out = fdopen(fd, "w");
|
||
|
if (conn_out == NULL) {
|
||
|
perror("fdopen");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
setvbuf(conn_in, NULL, _IOLBF, 256);
|
||
|
setvbuf(conn_out, NULL, _IOLBF, 256);
|
||
|
|
||
|
while (fgets(buf, sizeof buf, stdin) != NULL) {
|
||
|
if (buf[0] == 'W') {
|
||
|
fprintf(conn_out, "%.*s\r\n", (int)(strlen(buf + 1) - 1), buf + 1);
|
||
|
fprintf(stderr, ">>> %.*s\n", (int)(strlen(buf + 1) - 1), buf + 1);
|
||
|
} else if (buf[0] == 'C') {
|
||
|
fprintf(stderr, "Closing.\n");
|
||
|
fclose(conn_in);
|
||
|
fclose(conn_out);
|
||
|
exit(0);
|
||
|
} else if (buf[0] == 'R') {
|
||
|
int lines = 0;
|
||
|
|
||
|
sscanf(buf + 1, "%d", &lines);
|
||
|
do {
|
||
|
if (fgets(buf, sizeof buf, conn_in) == NULL) {
|
||
|
if (ferror(conn_in)) {
|
||
|
fprintf(stderr, "ERROR\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
fprintf(stderr, "CLOSED\n");
|
||
|
return 0;
|
||
|
}
|
||
|
fprintf(stderr, "<<< %s", buf);
|
||
|
} while (--lines > 0);
|
||
|
} else if (buf[0] == 'T') {
|
||
|
int infofd;
|
||
|
|
||
|
tls++;
|
||
|
{
|
||
|
struct tls_start_proxy_args a = tls_start_proxy_defaultargs();
|
||
|
a.fd = fd;
|
||
|
a.client_p = client_p;
|
||
|
a.ctx = ctx;
|
||
|
a.infofd = &infofd;
|
||
|
r = tls_start_proxy(a, NULL);
|
||
|
}
|
||
|
assert(r != 1);
|
||
|
if (r != 0) {
|
||
|
fprintf(stderr, "tls_start_proxy failed: %d\n", r);
|
||
|
switch (r) {
|
||
|
case -1:
|
||
|
fputs("socketpair", stderr); break;
|
||
|
case 2:
|
||
|
fputs("FD_SETSIZE exceeded", stderr); break;
|
||
|
case -3:
|
||
|
fputs("pipe", stderr); break;
|
||
|
case -4:
|
||
|
fputs("fork", stderr); break;
|
||
|
case -5:
|
||
|
fputs("dup2", stderr); break;
|
||
|
default:
|
||
|
fputs("?", stderr);
|
||
|
}
|
||
|
if (r < 0)
|
||
|
perror("");
|
||
|
else
|
||
|
fputc('\n', stderr);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
r = read(infofd, infobuf, sizeof infobuf - 1);
|
||
|
if (r > 0) {
|
||
|
const char *info = infobuf;
|
||
|
const char *eol;
|
||
|
|
||
|
infobuf[r] = '\0';
|
||
|
while ((eol = strchr(info, '\n')) != NULL) {
|
||
|
fprintf(stderr, "+++ `%.*s'\n", eol - info, info);
|
||
|
info = eol+1;
|
||
|
}
|
||
|
close (infofd);
|
||
|
}
|
||
|
} else {
|
||
|
fprintf(stderr, "W... write line to network\n"
|
||
|
"R[n] read line (n lines) from network\n"
|
||
|
"C close\n"
|
||
|
"T start %sTLS proxy\n", tls ? "another " : "");
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|