1/* test.c */ 2/* $Id: test.c,v 1.1 2001/09/17 19:06:59 bodo Exp $ */ 3 4#define L_PORT 9999 5#define C_PORT 443 6 7#include <arpa/inet.h> 8#include <assert.h> 9#include <errno.h> 10#include <fcntl.h> 11#include <netinet/in.h> 12#include <netinet/tcp.h> 13#include <stdlib.h> 14#include <stdio.h> 15#include <string.h> 16#include <sys/select.h> 17#include <sys/socket.h> 18#include <unistd.h> 19 20#include "test.h" 21#include "easy-tls.h" 22 23void test_process_init(int fd, int client_p, void *apparg) 24{ 25 fprintf(stderr, 26 "test_process_init(fd = %d, client_p = %d, apparg = %p)\n", fd, 27 client_p, apparg); 28} 29 30void test_errflush(int child_p, char *errbuf, size_t num, void *apparg) 31{ 32 fputs(errbuf, stderr); 33} 34 35int main(int argc, char *argv[]) 36{ 37 int s, fd, r; 38 FILE *conn_in; 39 FILE *conn_out; 40 char buf[256]; 41 SSL_CTX *ctx; 42 int client_p = 0; 43 int port; 44 int tls = 0; 45 char infobuf[TLS_INFO_SIZE + 1]; 46 47 if (argc > 1 && argv[1][0] == '-') { 48 fputs("Usage: test [port] -- server\n" 49 " test num.num.num.num [port] -- client\n", stderr); 50 exit(1); 51 } 52 53 if (argc > 1) { 54 if (strchr(argv[1], '.')) { 55 client_p = 1; 56 } 57 } 58 59 fputs(client_p ? "Client\n" : "Server\n", stderr); 60 61 { 62 struct tls_create_ctx_args a = tls_create_ctx_defaultargs(); 63 a.client_p = client_p; 64 a.certificate_file = "cert.pem"; 65 a.key_file = "cert.pem"; 66 a.ca_file = "cacerts.pem"; 67 68 ctx = tls_create_ctx(a, NULL); 69 if (ctx == NULL) 70 exit(1); 71 } 72 73 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 74 if (s == -1) { 75 perror("socket"); 76 exit(1); 77 } 78 79 if (client_p) { 80 struct sockaddr_in addr; 81 size_t addr_len = sizeof addr; 82 83 addr.sin_family = AF_INET; 84 assert(argc > 1); 85 if (argc > 2) 86 sscanf(argv[2], "%d", &port); 87 else 88 port = C_PORT; 89 addr.sin_port = htons(port); 90 addr.sin_addr.s_addr = inet_addr(argv[1]); 91 92 r = connect(s, &addr, addr_len); 93 if (r != 0) { 94 perror("connect"); 95 exit(1); 96 } 97 fd = s; 98 fprintf(stderr, "Connect (fd = %d).\n", fd); 99 } else { 100 /* server */ 101 { 102 int i = 1; 103 104 r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof i); 105 if (r == -1) { 106 perror("setsockopt"); 107 exit(1); 108 } 109 } 110 111 { 112 struct sockaddr_in addr; 113 size_t addr_len = sizeof addr; 114 115 if (argc > 1) 116 sscanf(argv[1], "%d", &port); 117 else 118 port = L_PORT; 119 addr.sin_family = AF_INET; 120 addr.sin_port = htons(port); 121 addr.sin_addr.s_addr = INADDR_ANY; 122 123 r = bind(s, &addr, addr_len); 124 if (r != 0) { 125 perror("bind"); 126 exit(1); 127 } 128 } 129 130 r = listen(s, 1); 131 if (r == -1) { 132 perror("listen"); 133 exit(1); 134 } 135 136 fprintf(stderr, "Listening at port %i.\n", port); 137 138 fd = accept(s, NULL, 0); 139 if (fd == -1) { 140 perror("accept"); 141 exit(1); 142 } 143 144 fprintf(stderr, "Accept (fd = %d).\n", fd); 145 } 146 147 conn_in = fdopen(fd, "r"); 148 if (conn_in == NULL) { 149 perror("fdopen"); 150 exit(1); 151 } 152 conn_out = fdopen(fd, "w"); 153 if (conn_out == NULL) { 154 perror("fdopen"); 155 exit(1); 156 } 157 158 setvbuf(conn_in, NULL, _IOLBF, 256); 159 setvbuf(conn_out, NULL, _IOLBF, 256); 160 161 while (fgets(buf, sizeof buf, stdin) != NULL) { 162 if (buf[0] == 'W') { 163 fprintf(conn_out, "%.*s\r\n", (int)(strlen(buf + 1) - 1), 164 buf + 1); 165 fprintf(stderr, ">>> %.*s\n", (int)(strlen(buf + 1) - 1), 166 buf + 1); 167 } else if (buf[0] == 'C') { 168 fprintf(stderr, "Closing.\n"); 169 fclose(conn_in); 170 fclose(conn_out); 171 exit(0); 172 } else if (buf[0] == 'R') { 173 int lines = 0; 174 175 sscanf(buf + 1, "%d", &lines); 176 do { 177 if (fgets(buf, sizeof buf, conn_in) == NULL) { 178 if (ferror(conn_in)) { 179 fprintf(stderr, "ERROR\n"); 180 exit(1); 181 } 182 fprintf(stderr, "CLOSED\n"); 183 return 0; 184 } 185 fprintf(stderr, "<<< %s", buf); 186 } while (--lines > 0); 187 } else if (buf[0] == 'T') { 188 int infofd; 189 190 tls++; 191 { 192 struct tls_start_proxy_args a = tls_start_proxy_defaultargs(); 193 a.fd = fd; 194 a.client_p = client_p; 195 a.ctx = ctx; 196 a.infofd = &infofd; 197 r = tls_start_proxy(a, NULL); 198 } 199 assert(r != 1); 200 if (r != 0) { 201 fprintf(stderr, "tls_start_proxy failed: %d\n", r); 202 switch (r) { 203 case -1: 204 fputs("socketpair", stderr); 205 break; 206 case 2: 207 fputs("FD_SETSIZE exceeded", stderr); 208 break; 209 case -3: 210 fputs("pipe", stderr); 211 break; 212 case -4: 213 fputs("fork", stderr); 214 break; 215 case -5: 216 fputs("dup2", stderr); 217 break; 218 default: 219 fputs("?", stderr); 220 } 221 if (r < 0) 222 perror(""); 223 else 224 fputc('\n', stderr); 225 exit(1); 226 } 227 228 r = read(infofd, infobuf, sizeof infobuf - 1); 229 if (r > 0) { 230 const char *info = infobuf; 231 const char *eol; 232 233 infobuf[r] = '\0'; 234 while ((eol = strchr(info, '\n')) != NULL) { 235 fprintf(stderr, "+++ `%.*s'\n", eol - info, info); 236 info = eol + 1; 237 } 238 close(infofd); 239 } 240 } else { 241 fprintf(stderr, "W... write line to network\n" 242 "R[n] read line (n lines) from network\n" 243 "C close\n" 244 "T start %sTLS proxy\n", tls ? "another " : ""); 245 } 246 } 247 return 0; 248} 249