Permalink
Browse files

Verification fix, client info option, version 1.0.7

  • Loading branch information...
szilu authored and Szilard Hajba committed Feb 24, 2009
1 parent 3dcdabb commit 13a085dfe9b3d274ded3bacc579eaee761aaf9aa
Showing with 147 additions and 22 deletions.
  1. +0 −8 Makefile
  2. +2 −2 Makefile.global
  3. +41 −1 README
  4. +104 −11 ssl_proxy.c
View
@@ -9,14 +9,6 @@ all: $(TARGET)
clean:
rm -f $(TARGET) core *.o
r_tag:
cvs tag -c -R rel-$(MAJOR_VERSION)_$(MINOR_VERSION)_$(MICRO_VERSION)
r_tgz:
cvs -d :ext:szilu@cvs.sourceforge.net:/cvsroot/sslproxy export -r rel-$(MAJOR_VERSION)_$(MINOR_VERSION)_$(MICRO_VERSION) -d sslproxy-$(VERSION) sslproxy
tar cvzf ../sslproxy-$(VERSION).tgz sslproxy-$(VERSION)
rm -rf sslproxy-$(VERSION)
release: r_tag r_tgz
$(TARGET): $(OBJS)
View
@@ -2,14 +2,14 @@ PREFIX = /usr
MAJOR_VERSION = 1
MINOR_VERSION = 0
MICRO_VERSION = 5
MICRO_VERSION = 7
VERSION = ${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}
CC = gcc
LD = gcc
CINCLUDE =
CFLAGS = -Wall -g3
CFLAGS = -Wall -g3 -DVERSION=\"$(VERSION)\"
LDFLAGS =
COPTS = $(CFLAGS) $(CINCLUDE) $(CCPRAGMA)
LDLIBS = -lssl -lcrypto
View
42 README
@@ -40,13 +40,15 @@ options.
-f Do not detach from the terminal and run in the
forground. Useful if you want to run SSL Proxy
from Symbion Daemon Tool.
-i Provide some info to the server about the
client (see below)
-s [<server host>:]<server port>
Specify the port, which SSL Proxy will listen
on (or address to bind to a specific interface).
-c [<client host>:]<client port>
Specify the TCP port, which SSL Proxy will
connect to as a client (The forwarding port).
-c unix:<client port>
-c unix:<socket path>
Specify the UNIX domain socket, which SSL Proxy
will connect to as a client (The forwarding port).
-m <max connection> SSL Proxy will accept maximum this number of
@@ -80,6 +82,44 @@ then the user must have read and write permission to the socket file.
The TCP sockets has no similar limitations, because they are not associated
with filesystem objects.
The file provided with the -v option can contain several CA certificates in
PEM format. If you use the -V (certificate directory) option, then each file
have to contain exactly ONE certificate. The files are looked up by the CA
subject name hash value, which must be available. You can create symlinks with
the c_rehash utility, contained in the openssl package.
Client info feature
===================
SSL Proxy can provide client information to the server in a special format.
This is a new feature in version 1.0.7, so I do not know of any server software
that can use this information except my own special purpose software. If I
receive information about any software available that uses this information, I
will publicate it on our website, www.symbion.hu.
The usage is very simple. You provide the -i option to SSL Proxy. When a
client connects, SSL Proxy connects to the server the usual way. But before
the data sent by the client is forwarded to the server, SSL Proxy sends an
information line to the server. This is an example of a HTTPS connection with
the -i option:
-----8<-----
szilu@maia:[~]$ nc -l -p 8080
#@ip=127.0.0.1 port=57223
GET / HTTP/1.1
Host: localhost:8443
User-Agent: Links (2.1pre37; Linux 2.6.27-11-eeepc i686; 80x24)
Accept: */*
Accept-Encoding: gzip, deflate
...
----->8-----
As you can see, an extra line beginning with '#@' is sent to the server. It
contains the IP address and the TCP port of the client and optionally the
common name (cn) of the client, if it has provided a certificate.
This information can be used for example for logging or access control purposes.
Examples
========
If you are running a HTTP server at port 80 which does not has SSL support,
View
@@ -16,7 +16,7 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define VERSION "1.0.5"
//#define VERSION "1.0.7"
#define MAX_CONNECTION 32
//#define CS_BUFFER_LEN 2
//#define SC_BUFFER_LEN 40
@@ -25,6 +25,7 @@
#define PEM_DIR "/etc/symbion"
#define CERT_FILE "cert.pem"
#define KEY_FILE "key.pem"
#define SLEEP_US 50000
#include <stdio.h>
#include <stdarg.h>
@@ -50,6 +51,7 @@
int debug_flag=0;
int fg_flag=0;
int info_flag=0;
int max_conn=MAX_CONNECTION;
int cs_buflen=CS_BUFFER_LEN, sc_buflen=SC_BUFFER_LEN;
char *server_addr="0.0.0.0";
@@ -58,6 +60,7 @@ char *client_addr="localhost";
int client_port=80;
char *cert_file=PEM_DIR"/"CERT_FILE, *key_file=PEM_DIR"/"KEY_FILE;
char *chroot_dir=NULL, *set_uid=NULL;
char *verify_ca_file=NULL, *verify_ca_dir=NULL;
struct passwd *pass;
int server_socket;
@@ -113,6 +116,12 @@ void plog(int level, const char *cls, const char *format,...) {
if (debug_flag) debug("LOG: %.256s: %.256s", cls, str);
}
void _sleep()
{
struct timeval tv={0, SLEEP_US};
select(0, NULL, NULL, NULL, &tv);
}
// ============================================== Server
int server_init(char *addr, int port, int maxconn) {
struct sockaddr_in server;
@@ -140,7 +149,7 @@ int server_init(char *addr, int port, int maxconn) {
void server_done(void) {
int ci;
shutdown(server_socket, 2);
usleep(100);
_sleep();
close(server_socket);
for (ci=0; ci<max_conn; ci++)
if (conn[ci].stat==cs_accept && conn[ci].stat==cs_connected) {
@@ -161,11 +170,18 @@ static RSA *tmp_rsa_cb(SSL *ssl, int export, int key_len) {
return rsa;
}
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
fprintf(stderr, "preverify: %d\n", preverify_ok);
return preverify_ok;
}
void server_ssl_init(void) {
// FILE *f;
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
server_ssl_ctx=SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_cipher_list(server_ssl_ctx, "HIGH");
if (!SSL_CTX_set_default_verify_paths(server_ssl_ctx)) {
fprintf(stderr, "cannot set default path\n");
exit(1);
@@ -182,6 +198,23 @@ void server_ssl_init(void) {
exit(1);
}
SSL_CTX_set_tmp_rsa_callback(server_ssl_ctx, tmp_rsa_cb);
if (verify_ca_file || verify_ca_dir) {
/*
STACK_OF(X509_NAME) *certs;
certs=SSL_load_client_CA_file(verify_ca_file);
if (certs) {
SSL_CTX_set_client_CA_list(server_ssl_ctx, certs);
} else {
fprintf(stderr,"error reading client CA list: %.256s\n",
ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
*/
SSL_CTX_load_verify_locations(server_ssl_ctx, verify_ca_file, verify_ca_dir);
SSL_CTX_set_verify(server_ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback);
}
// SSL_CTX_set_session_cache_mode(server_ssl_ctx, SSL_SESS_CACHE_OFF);
}
@@ -249,7 +282,7 @@ int conn_accept(void) {
// close(conn[i].server_sock);
// return -1;
// }
SSL_set_verify(conn[i].ssl_conn, 0, NULL);
// SSL_set_verify(conn[i].ssl_conn, 0, NULL);
BIO_set_nbio(SSL_get_rbio(conn[i].ssl_conn), 0);
BIO_set_nbio(SSL_get_wbio(conn[i].ssl_conn), 0);
fcntl(conn[i].server_sock, F_SETFL, O_NONBLOCK);
@@ -268,7 +301,7 @@ int conn_ssl_accept(Conn *conn) {
if (err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) {
return 1;
} else {
plog(LOG_ERR, "accept()", "Access failed: %.256s", ERR_error_string(err, NULL));
plog(LOG_ERR, "accept()", "Accept failed: %.256s", ERR_error_string(err, NULL));
ERR_print_errors_fp(stderr);
}
@@ -280,6 +313,22 @@ int conn_ssl_accept(Conn *conn) {
close(conn->server_sock);
conn->stat=cs_disconnected;
return -1;
/*
} else if (ret==1) {
// Successfull negotiation
X509 *peer;
if (!(peer=SSL_get_peer_certificate(conn->ssl_conn))
|| SSL_get_verify_result(conn->ssl_conn)!=X509_V_OK) {
unsigned long err=SSL_get_error(conn->ssl_conn, ret);
plog(LOG_ERR, "accept()", "SSL handshake: %.256s", ERR_error_string(err, NULL));
ERR_print_errors_fp(stderr);
debug("SSL_accept: disconnected.");
SSL_free(conn->ssl_conn);
close(conn->server_sock);
conn->stat=cs_disconnected;
return -1;
}
*/
}
// Connect to server (client side)
@@ -293,15 +342,25 @@ int conn_ssl_accept(Conn *conn) {
}
fcntl(conn->client_sock, F_SETFL, O_NONBLOCK);
conn->stat=cs_connecting;
if (connect(conn->client_sock, client_sa, client_sa_len)<0) {
/*
ret=connect(conn->client_sock, client_sa, client_sa_len);
if (ret<0) {
if (errno==EINPROGRESS) return 0;
plog(LOG_ERR, "connect()", strerror(errno));
close(conn->client_sock);
SSL_free(conn->ssl_conn);
close(conn->server_sock);
conn->stat=cs_disconnected;
return -1;
} else conn->stat=cs_connected;
} else {
conn->stat=cs_connected;
debug("Connection negotiated");
if (info_flag) {
conn->csbuf_e+=snprintf(conn->csbuf_b, cs_buflen, "#@ip=%s \r\n", "1.1.1.1");
debug("INFO: %s", conn->csbuf);
}
}
*/
return 0;
}
@@ -353,13 +412,14 @@ int main(int argc, char **argv) {
int c, pid, i;
char *p1, *p2;
while ((c=getopt(argc, argv, "hdfm:s:c:C:K:u:r:U:D:")) != EOF)
while ((c=getopt(argc, argv, "hdfim:s:c:C:K:u:r:v:V:U:D:")) != EOF)
switch (c) {
case 'h':
fprintf(stderr, "Symbion SSL proxy " VERSION "\n"
"usage: %.256s [-d] [-f] [-s <listen address>] [-c <client address>]\n"
"usage: %.256s [-d] [-f] [-i] [-s <listen address>] [-c <client address>]\n"
" [-m <max connection>] [-C <certificate file>] [-K <key file>]\n"
" [-u <user/uid>] [-r <chroot dir>]\n"
" [-v <trusted CA file>] [-V <trusted CA dir>]\n"
" [-U <upward buffer (default 2048)>] [-D <downward buffer (default 8192)>]\n"
" <lister address> = [<host>:]<port>\n"
" <client address> = [<host>:]<port> | unix:<path>\n", argv[0]);
@@ -371,6 +431,9 @@ int main(int argc, char **argv) {
case 'f':
fg_flag=1;
break;
case 'i':
info_flag=1;
break;
case 'm':
max_conn=atoi(optarg);
break;
@@ -413,6 +476,12 @@ int main(int argc, char **argv) {
case 'r':
chroot_dir=optarg;
break;
case 'v':
verify_ca_file=optarg;
break;
case 'V':
verify_ca_dir=optarg;
break;
case 'U':
cs_buflen=atoi(optarg);
break;
@@ -493,14 +562,38 @@ int main(int argc, char **argv) {
break;
case cs_connecting:
if (connect(cn->client_sock, client_sa, client_sa_len)<0) {
if (errno==EALREADY) break;
if (errno==EINPROGRESS) break;
// if (errno==EALREADY) break;
perror("connecting()");
plog(LOG_ERR, "connect()", strerror(errno));
close(cn->client_sock);
SSL_free(cn->ssl_conn);
close(cn->server_sock);
cn->stat=cs_disconnected;
} else cn->stat=cs_connected;
} else {
cn->stat=cs_connected;
debug("Connection negotiated");
if (info_flag) {
struct sockaddr_in client_addr;
unsigned int client_addr_len;
X509 *cert;
X509_NAME *xn=NULL;
char peer_cn[256]="";
getpeername(conn->server_sock,
(struct sockaddr *)&client_addr,
&client_addr_len);
cert=SSL_get_peer_certificate(conn->ssl_conn);
if (cert) {
xn=X509_get_subject_name(cert);
X509_NAME_get_text_by_NID(xn, NID_commonName, peer_cn, 256);
}
conn->csbuf_e+=snprintf(conn->csbuf_b, cs_buflen,
"#@ip=%s port=%d%s%s%s\r\n",
inet_ntoa(client_addr.sin_addr),
client_addr.sin_port, xn?" cn='":"", peer_cn, xn?"'":"");
debug("INFO: %s", conn->csbuf);
}
}
break;
case cs_connected:
// Check if data is available on client side
@@ -575,7 +668,7 @@ perror("connecting()");
if (cn->stat==cs_closing && cn->scbuf_e==cn->scbuf_b) conn_close_server(cn);
}
}
if (!event) usleep(100);
if (!event) _sleep();
}
return 0;
}

0 comments on commit 13a085d

Please sign in to comment.