1 /* simple wrapper program for STARTTLS
3 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
5 Author: Daiki Ueno <ueno@unixuser.org>
9 This file is not part of any package.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with GNU Emacs; see the file COPYING. If not, write to the
23 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA.
28 #include <sys/types.h>
38 #include <sys/socket.h>
40 #include <sys/ioctl.h>
46 #include <netinet/in.h>
51 #include "getaddrinfo.h"
53 #include "inet_ntop.h"
56 extern void tls_negotiate (int, const char *, const char *);
57 extern int tls_write(int, const char *, int);
58 extern int tls_read(int, char *, int);
59 extern int tls_pending();
61 static char *opt_cert_file = NULL, *opt_key_file = NULL;
68 printf ("%s (%s) %s\n"
69 "Copyright (C) 1999 Free Software Foundation, Inc.\n"
70 "This program comes with ABSOLUTELY NO WARRANTY.\n"
71 "This is free software, and you are welcome to redistribute it\n"
72 "under certain conditions. See the file COPYING for details.\n\n"
73 "Usage: %s [options] host port\n\n"
75 " --cert-file [file] specify certificate file\n"
76 " --key-file [file] specify private key file\n",
77 progname, PACKAGE, VERSION, progname);
84 tls_negotiate(tls_fd, opt_cert_file, opt_key_file);
88 tcp_connect (hostname, service)
89 const char *hostname, *service;
91 int server, _false = 0;
92 struct addrinfo *in, *in0, hints;
94 memset (&hints, 0, sizeof (hints));
95 hints.ai_family = AF_UNSPEC;
96 hints.ai_socktype = SOCK_STREAM;
97 if (getaddrinfo (hostname, service, &hints, &in0))
100 for (in = in0; in; in = in->ai_next)
102 server = socket (in->ai_family, in->ai_socktype, in->ai_protocol);
105 if (connect (server, in->ai_addr, in->ai_addrlen) < 0)
116 setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &_false,
127 int in = fileno (stdin), out = fileno (stdout),
130 struct pollfd readfds[2], writefds[1];
132 fd_set readfds, writefds;
134 char buffer[BUFSIZ], *retry;
135 struct sigaction act;
137 int this_option_optind = optind ? optind : 1;
138 int option_index = 0, c;
139 static struct option long_options[] =
141 {"cert-file", 1, 0, 'c'},
142 {"key-file", 1, 0, 'k'},
148 c = getopt_long (argc, argv, "c:k:", long_options, &option_index);
155 opt_cert_file = optarg;
158 opt_key_file = optarg;
166 if (optind+2 != argc)
172 tls_fd = tcp_connect (argv[optind], argv[optind+1]);
175 perror ("tcp_connect");
179 memset (&act, 0, sizeof (act));
180 act.sa_handler = do_tls_negotiate;
181 sigemptyset (&act.sa_mask);
182 act.sa_flags = SA_RESTART|SA_RESETHAND;
183 sigaction (SIGALRM, &act, NULL);
187 readfds[1].fd = tls_fd;
188 readfds[0].events = POLLIN;
189 readfds[1].events = POLLIN;
190 writefds[0].events = POLLOUT;
196 if (poll (readfds, 2, -1) == -1 && errno != EINTR)
199 FD_SET (tls_fd, &readfds);
200 FD_SET (in, &readfds);
201 if (select (tls_fd+1, &readfds, NULL, NULL, NULL) == -1
209 if (readfds[0].revents & POLLIN)
211 if (FD_ISSET (in, &readfds))
214 nbuffer = read (in, buffer, sizeof buffer -1);
218 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
221 writefds[0].fd = tls_fd;
222 if (poll (writefds, 1, -1) == -1)
225 FD_SET (tls_fd, &writefds);
226 if (select (tls_fd+1, NULL, &writefds, NULL, NULL) == -1)
232 wrote = tls_write(tls_fd, retry, nbuffer);
233 if (wrote < 0) goto finish;
237 if (readfds[1].revents & POLLIN)
239 if (FD_ISSET (tls_fd, &readfds))
243 nbuffer = tls_read(tls_fd, buffer, sizeof buffer -1);
246 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
249 writefds[0].fd = out;
250 if (poll (writefds, 1, -1) == -1)
253 FD_SET (out, &writefds);
254 if (select (out+1, NULL, &writefds, NULL, NULL) == -1)
260 wrote = write (out, retry, nbuffer);
261 if (wrote < 0) goto finish;