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>
49 #include "getaddrinfo.h"
51 #include "inet_ntop.h"
54 extern void tls_negotiate (int, const char *, const char *);
55 extern int tls_write(int, const char *, int);
56 extern int tls_read(int, char *, int);
57 extern int tls_pending();
59 static char *opt_cert_file = NULL, *opt_key_file = NULL;
60 static int tls_fd = -1;
66 printf ("%s (%s) %s\n"
67 "Copyright (C) 1999 Free Software Foundation, Inc.\n"
68 "This program comes with ABSOLUTELY NO WARRANTY.\n"
69 "This is free software, and you are welcome to redistribute it\n"
70 "under certain conditions. See the file COPYING for details.\n\n"
71 "Usage: %s [options] host port\n\n"
73 " --cert-file [file] specify certificate file\n"
74 " --key-file [file] specify private key file\n",
75 progname, PACKAGE, VERSION, progname);
82 tls_negotiate (tls_fd, opt_cert_file, opt_key_file);
86 tcp_connect (hostname, service)
87 const char *hostname, *service;
89 int server, _false = 0;
90 struct addrinfo *in, *in0, hints;
92 memset (&hints, 0, sizeof (hints));
93 hints.ai_family = AF_UNSPEC;
94 hints.ai_socktype = SOCK_STREAM;
95 if (getaddrinfo (hostname, service, &hints, &in0))
98 for (in = in0; in; in = in->ai_next)
100 server = socket (in->ai_family, in->ai_socktype, in->ai_protocol);
103 if (connect (server, in->ai_addr, in->ai_addrlen) < 0)
114 setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &_false,
125 int in = fileno (stdin), out = fileno (stdout),
127 struct pollfd readfds[2], writefds[1];
128 char buffer[BUFSIZ], *retry;
129 struct sigaction act;
132 int this_option_optind = optind ? optind : 1;
133 int option_index = 0, c;
134 static struct option long_options[] =
136 {"cert-file", 1, 0, 'c'},
137 {"key-file", 1, 0, 'k'},
143 c = getopt_long (argc, argv, "c:k:", long_options, &option_index);
150 opt_cert_file = optarg;
153 opt_key_file = optarg;
161 if (optind+2 != argc)
167 tls_fd = tcp_connect (argv[optind], argv[optind+1]);
170 perror ("tcp_connect");
174 memset (&act, 0, sizeof (act));
175 act.sa_handler = do_tls_negotiate;
176 sigemptyset (&act.sa_mask);
177 sigaddset (&act.sa_mask, SIGALRM);
178 act.sa_flags = SA_RESTART|SA_RESETHAND;
179 sigaction (SIGALRM, &act, NULL);
182 readfds[1].fd = tls_fd;
183 readfds[0].events = POLLIN;
184 readfds[1].events = POLLIN;
185 writefds[0].events = POLLOUT;
191 sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
192 ready = poll (readfds, 2, -1);
193 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
194 if (ready == -1 && errno != EINTR)
199 if (readfds[0].revents & POLLIN)
201 nbuffer = read (in, buffer, sizeof buffer -1);
205 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
207 writefds[0].fd = tls_fd;
208 sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
209 ready = poll (writefds, 1, -1);
210 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
211 if (ready == -1 && errno != EINTR)
216 wrote = tls_write(tls_fd, retry, nbuffer);
217 if (wrote < 0) goto finish;
220 if (readfds[1].revents & POLLIN)
223 nbuffer = tls_read(tls_fd, buffer, sizeof buffer -1);
226 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
228 writefds[0].fd = out;
229 sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
230 ready = poll (writefds, 1, -1);
231 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
232 if (ready == -1 && errno != EINTR)
237 wrote = write (out, retry, nbuffer);
238 if (wrote < 0) goto finish;