X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=popproxy.c;h=5e3a91f909015b3081e71e51311a522adccbfe85;hb=420d54ee44ea5495b62e3539df67b9bc3bffba99;hp=3a12f715eea183160a560302486e3573729970db;hpb=7d2ac978e497f976b43f35af1ab27b82c842c182;p=cascardo%2Frnetproxy.git diff --git a/popproxy.c b/popproxy.c index 3a12f71..5e3a91f 100644 --- a/popproxy.c +++ b/popproxy.c @@ -25,22 +25,27 @@ #include #include #include +#include #include "log.h" #include "pop.h" #include "hcconn.h" +#include "hcconn_ssl.h" #include "tcp_connect.h" +#include "usermap.h" + #define CONFFILE SYSCONFDIR "/popproxy.conf" struct pop_address { char *server; char *port; + int ssl; }; static HCConn * -server_conn_new (char *server, char *port) +server_conn_new (char *server, char *port, int ssl) { int fd; HCConn *conn; @@ -53,15 +58,16 @@ server_conn_new (char *server, char *port) return NULL; } conn = hc_conn_new (NULL, NULL); - ssl_conn = hc_conn_new (NULL, NULL); r = hc_conn_set_driver_channel (conn, fd); if (r != 0) { - hc_conn_close (ssl_conn); hc_conn_close (conn); close (fd); return NULL; } + if (!ssl) + return conn; + ssl_conn = hc_conn_new (NULL, NULL); r = hc_conn_set_driver_ssl_client (ssl_conn, conn); if (r != 0) { @@ -72,6 +78,40 @@ server_conn_new (char *server, char *port) return ssl_conn; } +static HCConn * +client_conn_new (int fd) +{ + HCConn *conn; + HCConn *ssl_conn; + HCConn *pop_conn; + int r; + conn = hc_conn_new (NULL, NULL); + r = hc_conn_set_driver_channel (conn, fd); + if (r != 0) + { + hc_conn_close (conn); + close (fd); + return NULL; + } + ssl_conn = hc_conn_new (NULL, NULL); + hc_conn_set_driver_ssl_server (ssl_conn, conn); + if (r != 0) + { + hc_conn_close (ssl_conn); + hc_conn_close (conn); + return NULL; + } + pop_conn = hc_conn_new (NULL, NULL); + r = hc_conn_set_driver_pop (pop_conn, ssl_conn); + if (r != 0) + { + hc_conn_close (pop_conn); + hc_conn_close (ssl_conn); + return NULL; + } + return pop_conn; +} + static void push_other (HCConn *conn, HCEvent event, gpointer data) { @@ -91,13 +131,34 @@ push_other (HCConn *conn, HCEvent event, gpointer data) } static void -new_client (int fd, struct sockaddr *addr, socklen_t saddr, gpointer data) +ssl_connected (HCConn *client_conn, HCEvent event, gpointer data) { - HCConn *conn; - HCConn *pop_conn; + struct pop_address *address = data; HCConn *server_conn; + if (event != HC_EVENT_CONNECT) + { + g_debug ("Did not get connect event when trying to handshake:" + " got %d", event); + hc_conn_close (client_conn); + return; + } + server_conn = server_conn_new (address->server, address->port, + address->ssl); + if (server_conn == NULL) + { + g_debug ("Failure to create connection to server."); + hc_conn_close (client_conn); + return; + } + hc_conn_set_callback (client_conn, push_other, server_conn); + hc_conn_set_callback (server_conn, push_other, client_conn); +} + +static void +new_client (int fd, struct sockaddr *addr, socklen_t saddr, gpointer data) +{ + HCConn *client_conn; struct pop_address *address = data; - int r; if (fd < 0) { g_critical ("Server has received an error event."); @@ -108,32 +169,16 @@ new_client (int fd, struct sockaddr *addr, socklen_t saddr, gpointer data) g_message ("Received connection from %s.", inet_ntoa (((struct sockaddr_in *) addr)->sin_addr)); - server_conn = server_conn_new (address->server, address->port); - if (server_conn == NULL) + client_conn = client_conn_new (fd); + if (client_conn == NULL) { return; } - conn = hc_conn_new (NULL, NULL); - r = hc_conn_set_driver_channel (conn, fd); - if (r != 0) - { - hc_conn_close (server_conn); - hc_conn_close (conn); - close (fd); - return; - } - pop_conn = hc_conn_new (NULL, NULL); - r = hc_conn_set_driver_pop (pop_conn, conn); - if (r != 0) - { - hc_conn_close (server_conn); - hc_conn_close (pop_conn); - hc_conn_close (conn); - return; - } - hc_conn_set_callback (pop_conn, push_other, server_conn); - hc_conn_set_callback (server_conn, push_other, pop_conn); + if (address->ssl) + hc_conn_set_callback (client_conn, ssl_connected, address); + else + ssl_connected (client_conn, HC_EVENT_CONNECT, address); } @@ -160,8 +205,14 @@ int main (int argc, char **argv) gchar *port; gchar *server_address; gchar *server_port; + int server_ssl; + gchar *certfile; + gchar *ssl_keyfile; + gchar *policy; struct pop_address pop_address; + signal (SIGPIPE, SIG_IGN); + gnutls_global_init (); configfile = CONFFILE; @@ -190,6 +241,26 @@ int main (int argc, char **argv) exit (1); } + error = NULL; + certfile = g_key_file_get_string (keyfile, "global", "certfile", + &error); + if (certfile == NULL && error != NULL) + { + g_critical ("No certification file specified: %s.", + error->message); + g_error_free (error); + exit (1); + } + error = NULL; + ssl_keyfile = g_key_file_get_string (keyfile, "global", "keyfile", + &error); + if (ssl_keyfile == NULL && error != NULL) + { + ssl_keyfile = g_strdup (certfile); + g_error_free (error); + } + + error = NULL; conf_address = g_key_file_get_string (keyfile, "global", "address", &error); @@ -221,9 +292,32 @@ int main (int argc, char **argv) server_port = g_strdup ("995"); g_error_free (error); } + error = NULL; + server_ssl = g_key_file_get_boolean (keyfile, "global", "server_ssl", + &error); + if (server_ssl == 0 && error != NULL) + { + server_ssl = 0; + g_error_free (error); + } + + error = NULL; + policy = g_key_file_get_string (keyfile, "global", "policy", + &error); + if (policy == NULL && error != NULL) + { + policy = g_strdup ("deny"); + g_error_free (error); + } + + if (!strcmp (policy, "allow")) + ACCESS_DEFAULT = ACCESS_ALLOW; + g_free (policy); + pop_address.server = server_address; pop_address.port = server_port; + pop_address.ssl = server_ssl; server_fd = hc_tcp_server (port); if (server_fd < 0) @@ -236,6 +330,8 @@ int main (int argc, char **argv) pop_log_init (); g_message ("Listening at %s:%s.", conf_address, port); + if (ACCESS_DEFAULT == ACCESS_ALLOW) + g_message ("Authorizing users by default."); if (!foreground) daemon (0, 0); @@ -243,6 +339,11 @@ int main (int argc, char **argv) g_free (conf_address); g_free (port); + hc_conn_ssl_server_init_credentials (certfile, ssl_keyfile); + + g_free (certfile); + g_free (ssl_keyfile); + g_main_loop_run (g_main_loop_new (g_main_context_default (), TRUE)); gnutls_global_deinit ();