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 bool opt_assuan = false;
61 static int tls_fd = -1;
67 printf ("%s (%s) %s\n"
68 "Copyright (C) 1999 Free Software Foundation, Inc.\n"
69 "This program comes with ABSOLUTELY NO WARRANTY.\n"
70 "This is free software, and you are welcome to redistribute it\n"
71 "under certain conditions. See the file COPYING for details.\n\n"
72 "Usage: %s [options] host port\n\n"
74 " --cert-file [file] specify certificate file\n"
75 " --key-file [file] specify private key file\n"
76 " --help show this help\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,
123 redirect (fd, buffer, nbuffer, write_function)
127 int (*write_function) (int, const char *, int);
129 sigset_t mask, orig_mask;
130 struct pollfd writefds[1];
135 sigaddset (&mask, SIGALRM);
138 writefds[0].events = POLLOUT;
140 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
144 sigprocmask (SIG_SETMASK, &mask, &orig_mask);
145 ready = poll (writefds, 1, -1);
146 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
147 if (ready == -1 && errno != EINTR)
150 printf ("ERR 1 poll: %s\r\n", strerror (errno));
153 wrote = (*write_function)(fd, retry, nbuffer);
157 printf ("ERR 1 write: %s\r\n", strerror (errno));
168 int in = fileno (stdin), out = fileno (stdout),
170 struct pollfd readfds[2], writefds[1];
171 char buffer[BUFSIZ], *retry;
172 struct sigaction act;
175 int this_option_optind = optind ? optind : 1;
176 int option_index = 0, c;
177 static struct option long_options[] =
179 {"cert-file", 1, 0, 'c'},
180 {"key-file", 1, 0, 'k'},
182 {"assuan", 0, 0, 'A'},
188 c = getopt_long (argc, argv, "c:k:hA", long_options, &option_index);
195 opt_cert_file = optarg;
198 opt_key_file = optarg;
212 if (optind+2 != argc)
218 tls_fd = tcp_connect (argv[optind], argv[optind+1]);
221 perror ("tcp_connect");
225 memset (&act, 0, sizeof (act));
226 act.sa_handler = do_tls_negotiate;
227 sigemptyset (&act.sa_mask);
228 sigaddset (&act.sa_mask, SIGALRM);
229 act.sa_flags = SA_RESTART|SA_RESETHAND;
230 sigaction (SIGALRM, &act, NULL);
233 readfds[1].fd = tls_fd;
234 readfds[0].events = POLLIN;
235 readfds[1].events = POLLIN;
236 writefds[0].events = POLLOUT;
242 sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
243 ready = poll (readfds, 2, -1);
244 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
245 if (ready == -1 && errno != EINTR)
248 printf ("ERR 1 poll: %s\r\n", strerror (errno));
251 if (readfds[0].revents & POLLIN)
253 nbuffer = read (in, buffer, sizeof buffer -1);
257 redirect (tls_fd, buffer, nbuffer, tls_write);
259 if (readfds[1].revents & POLLIN)
262 nbuffer = tls_read(tls_fd, buffer, sizeof buffer -1);
265 redirect (out, buffer, nbuffer, write);