diff options
author | Joe Shaw <joe@ximian.com> | 2002-07-24 18:40:48 +0000 |
---|---|---|
committer | Joe Shaw <joeshaw@src.gnome.org> | 2002-07-24 18:40:48 +0000 |
commit | a7834a0529ad849f993ab2f528172ce7d982f76b (patch) | |
tree | 39828e06e3b9f43f43ad3955a8b652024bbca522 | |
parent | c35996871a030a442f66ba3da5451ea237f64bb2 (diff) | |
download | libsoup-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-- | ChangeLog | 48 | ||||
-rw-r--r-- | libsoup/soup-nss.c | 7 | ||||
-rw-r--r-- | libsoup/soup-nss.h | 3 | ||||
-rw-r--r-- | libsoup/soup-openssl.c | 43 | ||||
-rw-r--r-- | libsoup/soup-openssl.h | 2 | ||||
-rw-r--r-- | libsoup/soup-server.c | 12 | ||||
-rw-r--r-- | libsoup/soup-ssl-proxy.c | 18 | ||||
-rw-r--r-- | libsoup/soup-ssl.c | 29 | ||||
-rw-r--r-- | libsoup/soup-ssl.h | 6 |
9 files changed, 130 insertions, 38 deletions
@@ -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 */ |