summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Shaw <joe@ximian.com>2002-07-24 18:40:48 +0000
committerJoe Shaw <joeshaw@src.gnome.org>2002-07-24 18:40:48 +0000
commita7834a0529ad849f993ab2f528172ce7d982f76b (patch)
tree39828e06e3b9f43f43ad3955a8b652024bbca522
parentc35996871a030a442f66ba3da5451ea237f64bb2 (diff)
downloadlibsoup-a7834a0529ad849f993ab2f528172ce7d982f76b.tar.gz
Check the server mode and set up a client or server handshake
2002-07-24 Joe Shaw <joe@ximian.com> * src/libsoup/soup-nss.c: Check the server mode and set up a client or server handshake appropriately. * src/libsoup/soup-server.c (destroy_message): If we're supposed to close the connection, go ahead and close it. (message_new): Set the method to NULL, or else we'll segfault later. (conn_accept): Call soup_ssl_get_server_iochannel() instead. * src/libsoup/soup-ssl.c (soup_ssl_get_iochannel_real): Added. Does all of the heavy lifting from soup_ssl_get_iochannel(). Takes an argument for the SSL handshake type (client or server). Set IS_SERVER env var for the proxy if we are in server mode. When checking for the HUP, also get G_IO_ERR and G_IO_NVAL. Remove an extraneous ref. (soup_ssl_get_iochannel): Just a wrapper around the above for the client. (soup_ssl_get_server_iochannel): Added. A server-mode wrapper around the above. * src/soup-ssl-proxy/soup-openssl.c: Add a server mode global. (soup_openssl_write): if result is 0, return a G_IO_STATUS_EOF. (soup_openssl_get_iochannel): If we're in server mode, call SSL_accept() and SSL_connect() if we're in client mode. (soup_openssl_init): If we're in server mode, set it on the SSL context. * src/soup-ssl-proxy/soup-ssl-proxy.c (main): If SOUP_PROXY_DELAY is set, sleep for 20 seconds so we can attach gdb to it. Listen for G_IO_PRI messages as well.
-rw-r--r--ChangeLog48
-rw-r--r--libsoup/soup-nss.c7
-rw-r--r--libsoup/soup-nss.h3
-rw-r--r--libsoup/soup-openssl.c43
-rw-r--r--libsoup/soup-openssl.h2
-rw-r--r--libsoup/soup-server.c12
-rw-r--r--libsoup/soup-ssl-proxy.c18
-rw-r--r--libsoup/soup-ssl.c29
-rw-r--r--libsoup/soup-ssl.h6
9 files changed, 130 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 27fa8f8f..b0335213 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,47 @@
+2002-07-24 Joe Shaw <joe@ximian.com>
+
+ * src/libsoup/soup-nss.c: Check the server mode and set up a
+ client or server handshake appropriately.
+
+ * src/libsoup/soup-server.c (destroy_message): If we're supposed
+ to close the connection, go ahead and close it.
+ (message_new): Set the method to NULL, or else we'll segfault
+ later.
+ (conn_accept): Call soup_ssl_get_server_iochannel() instead.
+
+ * src/libsoup/soup-ssl.c (soup_ssl_get_iochannel_real): Added.
+ Does all of the heavy lifting from soup_ssl_get_iochannel().
+ Takes an argument for the SSL handshake type (client or server).
+ Set IS_SERVER env var for the proxy if we are in server mode.
+ When checking for the HUP, also get G_IO_ERR and G_IO_NVAL.
+ Remove an extraneous ref.
+ (soup_ssl_get_iochannel): Just a wrapper around the above for the
+ client.
+ (soup_ssl_get_server_iochannel): Added. A server-mode wrapper
+ around the above.
+
+ * src/soup-ssl-proxy/soup-openssl.c: Add a server mode global.
+ (soup_openssl_write): if result is 0, return a G_IO_STATUS_EOF.
+ (soup_openssl_get_iochannel): If we're in server mode, call
+ SSL_accept() and SSL_connect() if we're in client mode.
+ (soup_openssl_init): If we're in server mode, set it on the SSL
+ context.
+
+ * src/soup-ssl-proxy/soup-ssl-proxy.c (main): If SOUP_PROXY_DELAY
+ is set, sleep for 20 seconds so we can attach gdb to it. Listen
+ for G_IO_PRI messages as well.
+
2002-07-23 Joe Shaw <joe@ximian.com>
- * soup-auth.c (soup_auth_invalidate): Added. Removes the SoupAuth
- structure from the list of valid auths.
+ * src/libsoup/soup-auth.c (soup_auth_invalidate): Added. Removes
+ the SoupAuth structure from the list of valid auths.
- * soup-message.c (authorize_handler): Change the logic around when
- dealing with cached SoupAuths. If we previously were in the
- FAILED state, we might as well invalidate the old one and try it
- again. If we were in the SUCCESSFUL state, then something went
- wrong and we need to invalidate and start over again anyway.
+ * src/libsoup/soup-message.c (authorize_handler): Change the
+ logic around when dealing with cached SoupAuths. If we
+ previously were in the FAILED state, we might as well invalidate
+ the old one and try it again. If we were in the SUCCESSFUL state,
+ then something went wrong and we need to invalidate and start over
+ again anyway.
2002-07-16 Joe Shaw <joe@ximian.com>
diff --git a/libsoup/soup-nss.c b/libsoup/soup-nss.c
index edadbd93..599d3389 100644
--- a/libsoup/soup-nss.c
+++ b/libsoup/soup-nss.c
@@ -295,7 +295,7 @@ soup_nss_bad_cert (void *data, PRFileDesc *fd)
}
GIOChannel *
-soup_nss_get_iochannel (GIOChannel *sock)
+soup_nss_get_iochannel (GIOChannel *sock, SoupSSLType type)
{
SoupNSSChannel *chan;
GIOChannel *gchan;
@@ -322,7 +322,10 @@ soup_nss_get_iochannel (GIOChannel *sock)
}
SSL_OptionSet (fdesc, SSL_SECURITY, PR_TRUE);
- SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (type == SOUP_SSL_TYPE_CLIENT)
+ SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ else
+ SSL_OptionSet (fdesc, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
SSL_BadCertHook (fdesc, soup_nss_bad_cert, NULL);
if (SSL_ResetHandshake (fdesc, PR_FALSE) == PR_FAILURE) {
diff --git a/libsoup/soup-nss.h b/libsoup/soup-nss.h
index 1aaa0a45..2288144d 100644
--- a/libsoup/soup-nss.h
+++ b/libsoup/soup-nss.h
@@ -13,8 +13,9 @@
#include <glib.h>
#include <libsoup/soup-misc.h>
+#include <libsoup/soup-ssl.h>
-GIOChannel *soup_nss_get_iochannel (GIOChannel *sock);
+GIOChannel *soup_nss_get_iochannel (GIOChannel *sock, SoupSSLType type);
void soup_nss_set_security_policy (SoupSecurityPolicy policy);
diff --git a/libsoup/soup-openssl.c b/libsoup/soup-openssl.c
index d83a95d7..375f40a0 100644
--- a/libsoup/soup-openssl.c
+++ b/libsoup/soup-openssl.c
@@ -27,6 +27,8 @@
#include "soup-openssl.h"
+static gboolean server_mode = FALSE;
+
typedef struct {
GIOChannel channel;
gint fd;
@@ -233,7 +235,7 @@ soup_openssl_write (GIOChannel *channel,
if (result < 0) {
*bytes_written = 0;
- if (SSL_get_error (chan->ssl, result) == SSL_ERROR_WANT_READ)
+ if (SSL_get_error (chan->ssl, result) == SSL_ERROR_WANT_WRITE)
return G_IO_STATUS_AGAIN;
switch (errno) {
case EINVAL:
@@ -250,7 +252,8 @@ soup_openssl_write (GIOChannel *channel,
}
} else {
*bytes_written = result;
- return G_IO_STATUS_NORMAL;
+
+ return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
}
@@ -479,7 +482,7 @@ soup_openssl_get_iochannel (GIOChannel *sock)
g_return_val_if_fail (sock != NULL, NULL);
- if (!ssl_context && !soup_openssl_init ())
+ if (!ssl_context && !soup_openssl_init (server_mode))
goto THROW_CREATE_ERROR;
if (!soup_openssl_seed ())
@@ -504,12 +507,13 @@ soup_openssl_get_iochannel (GIOChannel *sock)
goto THROW_CREATE_ERROR;
}
- if (!SSL_use_RSAPrivateKey_file (ssl, ckey_file, 1)) {
+ if (!SSL_use_RSAPrivateKey_file (ssl, ckey_file, SSL_FILETYPE_PEM)) {
g_warning ("Unable to use private key file.");
+ ERR_print_errors_fp(stderr);
goto THROW_CREATE_ERROR;
}
- if (!SSL_use_certificate_file (ssl, ccert_file, 1)) {
+ if (!SSL_use_certificate_file (ssl, ccert_file, SSL_FILETYPE_PEM)) {
g_warning ("Unable to use certificate file.");
goto THROW_CREATE_ERROR;
}
@@ -531,7 +535,11 @@ soup_openssl_get_iochannel (GIOChannel *sock)
do {
fd_set ssl_fdset;
- err = SSL_connect (ssl);
+ if (server_mode)
+ err = SSL_accept (ssl);
+ else
+ err = SSL_connect (ssl);
+
err = SSL_get_error (ssl, err);
if (err == SSL_ERROR_WANT_READ) {
@@ -556,12 +564,15 @@ soup_openssl_get_iochannel (GIOChannel *sock)
goto THROW_CREATE_ERROR;
}
- cert = SSL_get_peer_certificate (ssl);
- if (!cert) {
- g_warning ("Server certificate unavailable");
- goto THROW_CREATE_ERROR;
+ if (!server_mode) {
+ cert = SSL_get_peer_certificate (ssl);
+ if (!cert) {
+ g_warning ("Server certificate unavailable");
+ goto THROW_CREATE_ERROR;
+ }
+ else
+ X509_free (cert);
}
- X509_free (cert);
chan = g_new0 (SoupOpenSSLChannel, 1);
chan->fd = sockfd;
@@ -580,7 +591,7 @@ soup_openssl_get_iochannel (GIOChannel *sock)
}
gboolean
-soup_openssl_init (void)
+soup_openssl_init (gboolean server)
{
static gchar *ssl_ca_file = NULL;
static gchar *ssl_ca_dir = NULL;
@@ -588,7 +599,13 @@ soup_openssl_init (void)
SSL_library_init ();
SSL_load_error_strings ();
- ssl_context = SSL_CTX_new (SSLv23_client_method ());
+ server_mode = server;
+
+ if (server_mode)
+ ssl_context = SSL_CTX_new (SSLv23_server_method ());
+ else
+ ssl_context = SSL_CTX_new (SSLv23_client_method ());
+
if (!ssl_context) {
g_warning ("Unable to initialize OpenSSL library");
return FALSE;
diff --git a/libsoup/soup-openssl.h b/libsoup/soup-openssl.h
index 2a00983b..dbcd25a7 100644
--- a/libsoup/soup-openssl.h
+++ b/libsoup/soup-openssl.h
@@ -18,6 +18,6 @@ GIOChannel *soup_openssl_get_iochannel (GIOChannel *sock);
void soup_openssl_set_security_policy (SoupSecurityPolicy policy);
-gboolean soup_openssl_init (void);
+gboolean soup_openssl_init (gboolean server_mode);
#endif /* SOUP_OPENSSL_H */
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 38ead4c1..a2124b83 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -235,19 +235,24 @@ destroy_message (SoupMessage *msg)
SoupServerMessage *server_msg = msg->priv->server_msg;
if (server_sock) {
+ GIOChannel *chan;
+
+ chan = soup_socket_get_iochannel (server_sock);
+
/*
* Close the socket if we're using HTTP/1.0 and
* "Connection: keep-alive" isn't specified, or if we're
* using HTTP/1.1 and "Connection: close" was specified.
*/
- if (check_close_connection (msg))
+ if (check_close_connection (msg)) {
+ g_io_channel_close (chan);
soup_socket_unref (server_sock);
+ }
else {
/*
* Listen for another request on this connection
*/
ServerConnectData *data;
- GIOChannel *chan;
data = g_new0 (ServerConnectData, 1);
data->server = msg->priv->server;
@@ -911,6 +916,7 @@ message_new (SoupServer *server)
*/
msg = soup_message_new (NULL, NULL);
if (msg) {
+ msg->method = NULL;
msg->priv->server = server;
soup_server_ref (server);
}
@@ -977,7 +983,7 @@ conn_accept (GIOChannel *serv_chan,
chan = soup_socket_get_iochannel (sock);
if (server->proto == SOUP_PROTOCOL_HTTPS) {
- chan = soup_ssl_get_iochannel (chan);
+ chan = soup_ssl_get_server_iochannel (chan);
g_io_channel_unref (sock->iochannel);
g_io_channel_ref (chan);
sock->iochannel = chan;
diff --git a/libsoup/soup-ssl-proxy.c b/libsoup/soup-ssl-proxy.c
index 8b26b247..1a3ea991 100644
--- a/libsoup/soup-ssl-proxy.c
+++ b/libsoup/soup-ssl-proxy.c
@@ -33,6 +33,8 @@ static gint ssl_library = 0; /* -1 = fail,
1 = openssl */
static SoupSecurityPolicy ssl_security_level = SOUP_SECURITY_DOMESTIC;
+static gboolean server_mode = FALSE;
+
static GMainLoop *loop;
static void
@@ -58,7 +60,8 @@ soup_ssl_proxy_init (void)
ssl_library = -1;
#ifdef HAVE_OPENSSL_SSL_H
- if (ssl_library == -1) ssl_library = soup_openssl_init () ? 1 : -1;
+ if (ssl_library == -1)
+ ssl_library = soup_openssl_init (server_mode) ? 1 : -1;
#endif
if (ssl_library == -1) return;
@@ -131,6 +134,11 @@ main (int argc, char** argv)
GIOChannel *read_chan, *write_chan, *sock_chan;
int sockfd, secpol, flags;
+ if (getenv ("SOUP_PROXY_DELAY")) {
+ g_warning ("Proxy delay set: sleeping for 20 seconds");
+ sleep (20);
+ }
+
loop = g_main_new (FALSE);
env = getenv ("SOCKFD");
@@ -148,6 +156,10 @@ main (int argc, char** argv)
secpol = atoi (env);
soup_ssl_proxy_set_security_policy (secpol);
+ env = getenv ("IS_SERVER");
+ if (env)
+ server_mode = TRUE;
+
read_chan = g_io_channel_unix_new (STDIN_FILENO);
if (!read_chan)
g_error ("Unable to open STDIN");
@@ -170,12 +182,12 @@ main (int argc, char** argv)
g_error ("Unable to establish SSL connection");
g_io_add_watch (read_chan,
- G_IO_IN | G_IO_HUP | G_IO_ERR,
+ G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR,
(GIOFunc) soup_ssl_proxy_readwrite,
sock_chan);
g_io_add_watch (sock_chan,
- G_IO_IN | G_IO_HUP | G_IO_ERR,
+ G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR,
(GIOFunc) soup_ssl_proxy_readwrite,
write_chan);
diff --git a/libsoup/soup-ssl.c b/libsoup/soup-ssl.c
index 05302cad..f16613ca 100644
--- a/libsoup/soup-ssl.c
+++ b/libsoup/soup-ssl.c
@@ -37,7 +37,7 @@
#ifdef SOUP_WIN32
GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
+soup_ssl_get_iochannel_real (GIOChannel *sock, SoupSSLType type)
{
return NULL;
}
@@ -46,11 +46,11 @@ soup_ssl_get_iochannel (GIOChannel *sock)
#ifdef HAVE_NSS
GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
+soup_ssl_get_iochannel_real (GIOChannel *sock, SoupSSLType type)
{
g_return_val_if_fail (sock != NULL, NULL);
- return soup_nss_get_iochannel (sock);
+ return soup_nss_get_iochannel (sock, type);
}
#else /* HAVE_NSS */
@@ -63,8 +63,8 @@ soup_ssl_hup_waitpid (GIOChannel *source, GIOCondition condition, gpointer ppid)
return FALSE;
}
-GIOChannel *
-soup_ssl_get_iochannel (GIOChannel *sock)
+static GIOChannel *
+soup_ssl_get_iochannel_real (GIOChannel *sock, SoupSSLType type)
{
GIOChannel *new_chan;
int sock_fd;
@@ -101,6 +101,9 @@ soup_ssl_get_iochannel (GIOChannel *sock)
putenv (g_strdup_printf ("SECURITY_POLICY=%d",
soup_get_security_policy ()));
+ if (type == SOUP_SSL_TYPE_SERVER)
+ putenv ("IS_SERVER=1");
+
execl (BINDIR G_DIR_SEPARATOR_S SSL_PROXY_NAME,
BINDIR G_DIR_SEPARATOR_S SSL_PROXY_NAME,
NULL);
@@ -116,11 +119,9 @@ soup_ssl_get_iochannel (GIOChannel *sock)
fcntl (pair [1], F_SETFL, flags | O_NONBLOCK);
new_chan = g_io_channel_unix_new (pair [1]);
- g_io_add_watch (new_chan, G_IO_HUP,
+ g_io_add_watch (new_chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
soup_ssl_hup_waitpid, GINT_TO_POINTER (pid));
- /* FIXME: Why is this needed?? */
- g_io_channel_ref (new_chan);
return new_chan;
ERROR:
@@ -133,3 +134,15 @@ soup_ssl_get_iochannel (GIOChannel *sock)
#endif /* HAVE_NSS */
#endif /* SOUP_WIN32 */
+
+GIOChannel *
+soup_ssl_get_iochannel (GIOChannel *sock)
+{
+ return soup_ssl_get_iochannel_real (sock, SOUP_SSL_TYPE_CLIENT);
+}
+
+GIOChannel *
+soup_ssl_get_server_iochannel (GIOChannel *sock)
+{
+ return soup_ssl_get_iochannel_real (sock, SOUP_SSL_TYPE_SERVER);
+}
diff --git a/libsoup/soup-ssl.h b/libsoup/soup-ssl.h
index 0cfd438b..c73a82b9 100644
--- a/libsoup/soup-ssl.h
+++ b/libsoup/soup-ssl.h
@@ -13,6 +13,12 @@
#include <glib.h>
+typedef enum {
+ SOUP_SSL_TYPE_CLIENT = 0,
+ SOUP_SSL_TYPE_SERVER
+} SoupSSLType;
+
GIOChannel *soup_ssl_get_iochannel (GIOChannel *sock);
+GIOChannel *soup_ssl_get_server_iochannel (GIOChannel *sock);
#endif /* SOUP_SSL_H */