| /* 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; |
| } |