1 /* TLSv1 filter for STARTTLS extension.
3 Copyright (C) 1999, 2000 Daiki Ueno <ueno@unixuser.org>
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>
35 #include <openssl/lhash.h>
36 #include <openssl/bn.h>
37 #include <openssl/err.h>
38 #include <openssl/pem.h>
39 #include <openssl/x509.h>
40 #include <openssl/ssl.h>
46 #ifdef NEED_ADDRINFO_H
51 #include <sys/socket.h>
53 #include <sys/ioctl.h>
59 #include <netinet/in.h>
63 static SSL_CTX *tls_ctx = NULL;
64 static SSL *tls_conn = NULL;
67 static char *opt_cert_file = NULL, *opt_key_file = NULL;
68 static int opt_verify = 0;
71 tls_ssl_ctx_new (cert_file, key_file)
72 const char *cert_file, *key_file;
74 SSL_load_error_strings ();
75 SSLeay_add_ssl_algorithms ();
77 tls_ctx = SSL_CTX_new (TLSv1_client_method());
81 SSL_CTX_set_options (tls_ctx, SSL_OP_ALL /* Work around all known bugs */);
85 if (SSL_CTX_use_certificate_file (tls_ctx, cert_file,
86 SSL_FILETYPE_PEM) <= 0)
90 if (SSL_CTX_use_PrivateKey_file (tls_ctx, key_file,
91 SSL_FILETYPE_PEM) <= 0)
93 if (!SSL_CTX_check_private_key (tls_ctx))
97 SSL_CTX_set_verify (tls_ctx, SSL_VERIFY_NONE, NULL);
107 SSL_SESSION *session;
111 tls_conn = (SSL *) SSL_new (ctx);
116 if (!SSL_set_fd (tls_conn, s))
119 SSL_set_connect_state (tls_conn);
121 if (SSL_connect (tls_conn) <= 0)
123 session = SSL_get_session (tls_conn);
125 SSL_CTX_remove_session (ctx, session);
135 tls_connect (hostname, service)
136 const char *hostname, *service;
138 struct protoent *proto;
139 struct addrinfo *in, hints;
140 int server, false = 0;
142 proto = getprotobyname ("tcp");
146 memset (&hints, 0, sizeof (hints));
147 hints.ai_family = AF_UNSPEC;
148 hints.ai_socktype = SOCK_STREAM;
149 hints.ai_protocol = proto->p_proto;
151 if (getaddrinfo (hostname, service, &hints, &in) < 0)
154 server = socket (in->ai_family, in->ai_socktype, 0);
158 if (setsockopt (server, SOL_SOCKET, SO_KEEPALIVE,
159 (const char *) &false, sizeof (false)))
162 if (connect (server, in->ai_addr, in->ai_addrlen) < 0)
175 if (tls_ssl_ctx_new (opt_cert_file, opt_key_file) == -1)
178 (void) tls_ssl_new (tls_ctx, tls_fd); /* Negotiation has done. */
183 const char *progname;
185 printf ("%s (%s) %s\n"
186 "Copyright (C) 1999 Free Software Foundation, Inc.\n"
187 "This program comes with ABSOLUTELY NO WARRANTY.\n"
188 "This is free software, and you are welcome to redistribute it\n"
189 "under certain conditions. See the file COPYING for details.\n\n"
190 "Usage: %s [options] host port\n\n"
192 " --cert-file [file] specify certificate file\n"
193 " --key-file [file] specify private key file\n"
194 " --verify [level] set verification level\n",
195 progname, PACKAGE, VERSION, progname);
203 int in = fileno (stdin), out = fileno (stdout),
205 fd_set readfds, writefds;
206 char buffer[BUFSIZ], *retry;
207 struct sigaction act;
209 int this_option_optind = optind ? optind : 1;
210 int option_index = 0, c;
211 static struct option long_options[] =
213 {"cert-file", 1, 0, 'c'},
214 {"key-file", 1, 0, 'k'},
215 {"verify", 1, 0, 'v'},
221 c = getopt_long (argc, argv, "c:k:v:f", long_options, &option_index);
228 opt_cert_file = optarg;
231 opt_key_file = optarg;
234 opt_verify = atoi (optarg);
237 usage (basename (argv[0]));
242 if (optind+2 != argc)
244 usage (basename (argv[0]));
248 tls_fd = tls_connect (argv[optind], argv[optind+1]);
251 perror ("tls_connect");
255 memset (&act, 0, sizeof (act));
256 act.sa_handler = tls_negotiate;
257 sigemptyset (&act.sa_mask);
258 act.sa_flags = SA_RESTART|SA_RESETHAND;
259 sigaction (SIGALRM, &act, NULL);
263 FD_SET (tls_fd, &readfds);
264 FD_SET (in, &readfds);
265 if (select (tls_fd+1, &readfds, NULL, NULL, NULL) == -1
271 if (FD_ISSET (in, &readfds))
273 nbuffer = read (in, buffer, sizeof buffer -1);
277 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
279 FD_SET (tls_fd, &writefds);
280 if (select (tls_fd+1, NULL, &writefds, NULL, NULL) == -1)
286 wrote = SSL_write (tls_conn, retry, nbuffer);
288 wrote = write (tls_fd, retry, nbuffer);
289 if (wrote < 0) goto finish;
292 if (FD_ISSET (tls_fd, &readfds))
295 nbuffer = SSL_read (tls_conn, buffer, sizeof buffer -1);
297 nbuffer = read (tls_fd, buffer, sizeof buffer -1);
300 for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
302 FD_SET (out, &writefds);
303 if (select (out+1, NULL, &writefds, NULL, NULL) == -1)
308 wrote = write (out, retry, nbuffer);
309 if (wrote < 0) goto finish;