202f63bb284e739acdd2000f0907ef145fd60d17
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <sys/types.h>
19 #include <sys/socket.h>
24 #include <tls_socket.h>
25 #include <utils/host.h>
26 #include <credentials/sets/mem_cred.h>
29 * Print usage information
31 static void usage(FILE *out
, char *cmd
)
33 fprintf(out
, "usage:\n");
34 fprintf(out
, " %s --connect <address> --port <port> [--cert <file>]+\n", cmd
);
35 fprintf(out
, " %s --listen <address> --port <port> --key <key> [--cert <file>]+ --oneshot\n", cmd
);
39 * Stream between stdio and TLS socket
41 static int stream(int fd
, tls_socket_t
*tls
)
52 if (select(fd
+ 1, &set
, NULL
, NULL
, NULL
) == -1)
56 if (FD_ISSET(fd
, &set
))
58 if (!tls
->read(tls
, &data
))
60 fprintf(stderr
, "TLS read error\n");
65 ignore_result(write(0, data
.ptr
, data
.len
));
69 if (FD_ISSET(0, &set
))
74 len
= read(0, buf
, sizeof(buf
));
81 if (!tls
->write(tls
, chunk_create(buf
, len
)))
83 fprintf(stderr
, "TLS write error\n");
94 static int client(int fd
, host_t
*host
, identification_t
*server
)
99 if (connect(fd
, host
->get_sockaddr(host
),
100 *host
->get_sockaddr_len(host
)) == -1)
102 fprintf(stderr
, "connecting to %#H failed: %m\n", host
);
105 tls
= tls_socket_create(FALSE
, server
, NULL
, fd
);
110 res
= stream(fd
, tls
);
118 static int serve(int fd
, host_t
*host
, identification_t
*server
, bool oneshot
)
123 if (bind(fd
, host
->get_sockaddr(host
),
124 *host
->get_sockaddr_len(host
)) == -1)
126 fprintf(stderr
, "binding to %#H failed: %m\n", host
);
129 if (listen(fd
, 1) == -1)
131 fprintf(stderr
, "listen to %#H failed: %m\n", host
);
137 cfd
= accept(fd
, host
->get_sockaddr(host
), host
->get_sockaddr_len(host
));
140 fprintf(stderr
, "accept failed: %m\n");
143 fprintf(stderr
, "%#H connected\n", host
);
145 tls
= tls_socket_create(TRUE
, server
, NULL
, cfd
);
151 fprintf(stderr
, "%#H disconnected\n", host
);
160 * In-Memory credential set
162 static mem_cred_t
*creds
;
165 * Load certificate from file
167 static bool load_certificate(char *filename
)
171 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
172 BUILD_FROM_FILE
, filename
, BUILD_END
);
175 fprintf(stderr
, "loading certificate from '%s' failed\n", filename
);
178 creds
->add_cert(creds
, TRUE
, cert
);
183 * Load private key from file
185 static bool load_key(char *filename
)
189 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, KEY_RSA
,
190 BUILD_FROM_FILE
, filename
, BUILD_END
);
193 fprintf(stderr
, "loading key from '%s' failed\n", filename
);
196 creds
->add_key(creds
, key
);
203 static void cleanup()
205 lib
->credmgr
->remove_set(lib
->credmgr
, &creds
->set
);
206 creds
->destroy(creds
);
216 lib
->plugins
->load(lib
->plugins
, NULL
, PLUGINS
);
218 creds
= mem_cred_create();
219 lib
->credmgr
->add_set(lib
->credmgr
, &creds
->set
);
224 int main(int argc
, char *argv
[])
226 char *address
= NULL
;
227 bool listen
= FALSE
, oneshot
= FALSE
;
228 int port
= 0, fd
, res
;
229 identification_t
*server
;
236 struct option long_opts
[] = {
237 {"help", no_argument
, NULL
, 'h' },
238 {"connect", required_argument
, NULL
, 'c' },
239 {"listen", required_argument
, NULL
, 'l' },
240 {"port", required_argument
, NULL
, 'p' },
241 {"cert", required_argument
, NULL
, 'x' },
242 {"key", required_argument
, NULL
, 'k' },
243 {"oneshot", no_argument
, NULL
, 'o' },
246 switch (getopt_long(argc
, argv
, "", long_opts
, NULL
))
251 usage(stdout
, argv
[0]);
254 if (!load_certificate(optarg
))
260 if (!load_key(optarg
))
271 usage(stderr
, argv
[0]);
283 usage(stderr
, argv
[0]);
288 if (!port
|| !address
)
290 usage(stderr
, argv
[0]);
293 if (oneshot
&& !listen
)
295 usage(stderr
, argv
[0]);
299 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
302 fprintf(stderr
, "opening socket failed: %m\n");
305 host
= host_create_from_dns(address
, 0, port
);
308 fprintf(stderr
, "resolving hostname %s failed\n", address
);
312 server
= identification_create_from_string(address
);
315 res
= serve(fd
, host
, server
, oneshot
);
319 res
= client(fd
, host
, server
);
323 server
->destroy(server
);