📄 easy-tls.c
字号:
/* -*- Mode: C; c-file-style: "bsd" -*- *//* * easy-tls.c -- generic TLS proxy. * $Id: easy-tls.c,v 1.4 2002/03/05 09:07:16 bodo Exp $ *//* (c) Copyright 1999 Bodo Moeller. All rights reserved. This is free software; you can redistributed and/or modify it unter the terms of either - the GNU General Public License as published by the Free Software Foundation, version 1, or (at your option) any later version, or - the following license:*//* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that each of the following * conditions is met: * * 1. Redistributions qualify as "freeware" or "Open Source Software" under * one of the following terms: * * (a) Redistributions are made at no charge beyond the reasonable cost of * materials and delivery. * * (b) Redistributions are accompanied by a copy of the Source Code * or by an irrevocable offer to provide a copy of the Source Code * for up to three years at the cost of materials and delivery. * Such redistributions must allow further use, modification, and * redistribution of the Source Code under substantially the same * terms as this license. * * 2. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 3. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 4. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by Bodo Moeller." * (If available, substitute umlauted o for oe.) * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Bodo Moeller." * * THIS SOFTWARE IS PROVIDED BY BODO MOELLER ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BODO MOELLER OR * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Attribution for OpenSSL library: * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/) */static char const rcsid[] ="$Id: easy-tls.c,v 1.4 2002/03/05 09:07:16 bodo Exp $";#include <assert.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#include <sys/select.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <sys/utsname.h>#include <unistd.h>#include <openssl/crypto.h>#include <openssl/dh.h>#include <openssl/dsa.h>#include <openssl/err.h>#include <openssl/evp.h>#include <openssl/opensslv.h>#include <openssl/pem.h>#include <openssl/rand.h>#ifndef NO_RSA #include <openssl/rsa.h>#endif#include <openssl/ssl.h>#include <openssl/x509.h>#include <openssl/x509_vfy.h>#if OPENSSL_VERSION_NUMBER < 0x00904000L /* 0.9.4-dev */# error "This program needs OpenSSL 0.9.4 or later."#endif#include "easy-tls.h" /* include after <openssl/ssl.h> if both are needed */#if TLS_INFO_SIZE > PIPE_BUF# if PIPE_BUF < 512# error "PIPE_BUF < 512" /* non-POSIX */# endif# error "TLS_INFO_SIZE > PIPE_BUF"#endif/*****************************************************************************/#ifdef TLS_APP# include TLS_APP#endif/* Applications can define: * TLS_APP_PROCESS_INIT -- void ...(int fd, int client_p, void *apparg) * TLS_CUMULATE_ERRORS * TLS_ERROR_BUFSIZ * TLS_APP_ERRFLUSH -- void ...(int child_p, char *, size_t, void *apparg) */#ifndef TLS_APP_PROCESS_INIT# define TLS_APP_PROCESS_INIT(fd, client_p, apparg) ((void) 0)#endif#ifndef TLS_ERROR_BUFSIZ# define TLS_ERROR_BUFSIZ (10*160)#endif#if TLS_ERROR_BUFSIZ < 2 /* {'\n',0} */# error "TLS_ERROR_BUFSIZE is too small."#endif#ifndef TLS_APP_ERRFLUSH# define TLS_APP_ERRFLUSH tls_app_errflushstatic voidtls_app_errflush(int child_p, char *errbuf, size_t num, void *apparg){ fputs(errbuf, stderr);}#endif/*****************************************************************************/#ifdef DEBUG_TLS# define DEBUG_MSG(x) fprintf(stderr," %s\n",x)# define DEBUG_MSG2(x,y) fprintf(stderr, " %s: %d\n",x,y)static int tls_loop_count = 0;static int tls_select_count = 0;#else# define DEBUG_MSG(x) (void)0# define DEBUG_MSG2(x,y) (void)0#endifstatic void tls_rand_seed_uniquely(void);static void tls_proxy(int clear_fd, int tls_fd, int info_fd, SSL_CTX *ctx, int client_p);static int tls_socket_nonblocking(int fd);static int tls_child_p = 0;static void *tls_child_apparg;struct tls_start_proxy_argstls_start_proxy_defaultargs(void){ struct tls_start_proxy_args ret; ret.fd = -1; ret.client_p = -1; ret.ctx = NULL; ret.pid = NULL; ret.infofd = NULL; return ret;}/* Slice in TLS proxy process at fd. * Return value: * 0 ok (*pid is set to child's PID if pid != NULL), * < 0 look at errno * > 0 other error * (return value encodes place of error) * */inttls_start_proxy(struct tls_start_proxy_args a, void *apparg){ int fds[2] = {-1, -1}; int infofds[2] = {-1, -1}; int r, getfd, getfl; int ret; DEBUG_MSG2("tls_start_proxy fd", a.fd); DEBUG_MSG2("tls_start_proxy client_p", a.client_p); if (a.fd == -1 || a.client_p == -1 || a.ctx == NULL) return 1; if (a.pid != NULL) { *a.pid = 0; } if (a.infofd != NULL) { *a.infofd = -1; } r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (r == -1) return -1; if (a.fd >= FD_SETSIZE || fds[0] >= FD_SETSIZE) { ret = 2; goto err; } if (a.infofd != NULL) { r = pipe(infofds); if (r == -1) { ret = -3; goto err; } } r = fork(); if (r == -1) { ret = -4; goto err; } if (r == 0) { DEBUG_MSG("fork"); tls_child_p = 1; tls_child_apparg = apparg; close(fds[1]); if (infofds[0] != -1) close(infofds[0]); TLS_APP_PROCESS_INIT(a.fd, a.client_p, apparg); DEBUG_MSG("TLS_APP_PROCESS_INIT"); tls_proxy(fds[0], a.fd, infofds[1], a.ctx, a.client_p); exit(0); } if (a.pid != NULL) *a.pid = r; if (infofds[1] != -1) { close(infofds[1]); infofds[1] = -1; } /* install fds[1] in place of fd: */ close(fds[0]); fds[0] = -1; getfd = fcntl(a.fd, F_GETFD); getfl = fcntl(a.fd, F_GETFL); r = dup2(fds[1], a.fd); close(fds[1]); fds[1] = -1; if (r == -1) { ret = -5; goto err; } if (getfd != 1) fcntl(a.fd, F_SETFD, getfd); if (getfl & O_NONBLOCK) (void)tls_socket_nonblocking(a.fd); if (a.infofd != NULL) *a.infofd = infofds[0]; return 0; err: if (fds[0] != -1) close(fds[0]); if (fds[1] != -1) close(fds[1]); if (infofds[0] != -1) close(infofds[0]); if (infofds[1] != -1) close(infofds[1]); return ret;}/*****************************************************************************/static char errbuf[TLS_ERROR_BUFSIZ];static size_t errbuf_i = 0;static voidtls_errflush(void *apparg){ if (errbuf_i == 0) return; assert(errbuf_i < sizeof errbuf); assert(errbuf[errbuf_i] == 0); if (errbuf_i == sizeof errbuf - 1) { /* make sure we have a newline, even if string has been truncated */ errbuf[errbuf_i - 1] = '\n'; } /* TLS_APP_ERRFLUSH may modify the string as needed, * e.g. substitute other characters for \n for convenience */ TLS_APP_ERRFLUSH(tls_child_p, errbuf, errbuf_i, apparg); errbuf_i = 0;}static voidtls_errprintf(int flush, void *apparg, const char *fmt, ...){ va_list args; int r; if (errbuf_i < sizeof errbuf - 1) { size_t n; va_start(args, fmt); n = (sizeof errbuf) - errbuf_i; r = vsnprintf(errbuf + errbuf_i, n, fmt, args); if (r >= n) r = n - 1; if (r >= 0) { errbuf_i += r; } else { errbuf_i = sizeof errbuf - 1; errbuf[errbuf_i] = '\0'; } assert(errbuf_i < sizeof errbuf); assert(errbuf[errbuf_i] == 0); }#ifndef TLS_CUMULATE_ERRORS tls_errflush(apparg);#else if (flush) tls_errflush(apparg);#endif}/* app_prefix.. are for additional information provided by caller. * If OpenSSL error queue is empty, print default_text ("???" if NULL). */static char *tls_openssl_errors(const char *app_prefix_1, const char *app_prefix_2, const char *default_text, void *apparg){ static char reasons[255]; size_t reasons_i; unsigned long err; const char *file; int line; const char *data; int flags; char *errstring; int printed_something = 0; reasons_i = 0; assert(app_prefix_1 != NULL); assert(app_prefix_2 != NULL); if (default_text == NULL) default_text = "?""?""?"; while ((err = ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) { if (reasons_i < sizeof reasons) { size_t n; int r; n = (sizeof reasons) - reasons_i; r = snprintf(reasons + reasons_i, n, "%s%s", (reasons_i > 0 ? ", " : ""), ERR_reason_error_string(err)); if (r >= n) r = n - 1; if (r >= 0) { reasons_i += r; } else { reasons_i = sizeof reasons; } assert(reasons_i <= sizeof reasons); } errstring = ERR_error_string(err, NULL); assert(errstring != NULL); tls_errprintf(0, apparg, "OpenSSL error%s%s: %s:%s:%d:%s\n", app_prefix_1, app_prefix_2, errstring, file, line, (flags & ERR_TXT_STRING) ? data : ""); printed_something = 1; } if (!printed_something) { assert(reasons_i == 0); snprintf(reasons, sizeof reasons, "%s", default_text); tls_errprintf(0, apparg, "OpenSSL error%s%s: %s\n", app_prefix_1, app_prefix_2, default_text); }#ifdef TLS_CUMULATE_ERRORS tls_errflush(apparg);#endif assert(errbuf_i == 0); return reasons;}/*****************************************************************************/static int tls_init_done = 0;static inttls_init(void *apparg){ if (tls_init_done) return 0; SSL_load_error_strings();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -