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.
36 #include <arpa/inet.h>
38 #include <netinet/in.h>
41 #include <sys/socket.h>
42 #include <sys/types.h>
44 #include "getaddrinfo.h"
46 #include "inet_ntop.h"
51 #include "vasnprintf.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];
172 struct sigaction act;
173 sigset_t mask, orig_mask;
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 act.sa_flags = SA_RESTART|SA_RESETHAND;
229 sigaction (SIGALRM, &act, NULL);
232 sigaddset (&mask, SIGALRM);
235 readfds[1].fd = tls_fd;
236 readfds[0].events = POLLIN;
237 readfds[1].events = POLLIN;
243 sigprocmask (SIG_SETMASK, &mask, &orig_mask);
244 ready = poll (readfds, 2, -1);
245 sigprocmask (SIG_SETMASK, &orig_mask, NULL);
246 if (ready == -1 && errno != EINTR)
249 printf ("ERR 1 poll: %s\r\n", strerror (errno));
252 if (readfds[0].revents & POLLIN)
254 nbuffer = read (in, buffer, sizeof buffer -1);
257 redirect (tls_fd, buffer, nbuffer, tls_write);
259 if (readfds[1].revents & POLLIN)
261 nbuffer = tls_read (tls_fd, buffer, sizeof buffer -1);
264 redirect (out, buffer, nbuffer, write);
265 } while (tls_pending ());