[pan2: 167/268] working ssl yippie!
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 167/268] working ssl yippie!
- Date: Mon, 2 Jan 2012 15:52:02 +0000 (UTC)
commit bfb0c66a2b757dd013c470915e72045b71871c7d
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date: Sat Oct 22 20:27:03 2011 +0200
working ssl yippie!
pan.cbp | 1 -
pan/gui/pan.cc | 4 +-
pan/tasks/socket-impl-openssl.cc | 226 +++++++++++++++++++-------------------
pan/tasks/socket-impl-openssl.h | 4 +-
4 files changed, 116 insertions(+), 119 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
index 565221b..bb6cb1c 100644
--- a/pan.cbp
+++ b/pan.cbp
@@ -230,7 +230,6 @@
<Unit filename="pan/tasks/task-article.h" />
<Unit filename="pan/tasks/task-groups.cc" />
<Unit filename="pan/tasks/task-groups.h" />
- <Unit filename="pan/tasks/task-multipost.cc" />
<Unit filename="pan/tasks/task-multipost.h" />
<Unit filename="pan/tasks/task-post.cc" />
<Unit filename="pan/tasks/task-post.h" />
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 73af3a0..619633a 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -332,8 +332,8 @@ main (int argc, char *argv[])
// instantiate the queue...
WorkerPool worker_pool (4, true);
- GIOChannelSocket::Creator socket_creator;
-// GIOChannelSocketSSL::Creator socket_creator;
+// GIOChannelSocket::Creator socket_creator;
+ GIOChannelSocketSSL::Creator socket_creator;
Queue queue (data, data, &socket_creator, worker_pool,
prefs.get_flag ("work-online", true),
diff --git a/pan/tasks/socket-impl-openssl.cc b/pan/tasks/socket-impl-openssl.cc
index af19eca..66c0857 100644
--- a/pan/tasks/socket-impl-openssl.cc
+++ b/pan/tasks/socket-impl-openssl.cc
@@ -107,8 +107,8 @@ namespace
if (!inited)
{
- p_freeaddrinfo=NULL;
- p_getaddrinfo=NULL;
+ p_freeaddrinfo=0;
+ p_getaddrinfo=0;
#ifdef G_OS_WIN32
WSADATA wsaData;
@@ -118,11 +118,11 @@ namespace
if(GetSystemDirectory(sysdir,MAX_PATH)!=0)
{
- HMODULE lib=NULL;
- FARPROC pfunc=NULL;
- const char *libs[]={"ws2_32","wship6",NULL};
+ HMODULE lib=0;
+ FARPROC pfunc=0;
+ const char *libs[]={"ws2_32","wship6",0};
- for(const char **p=libs;*p!=NULL;++p)
+ for(const char **p=libs;*p!=0;++p)
{
g_snprintf(path,MAX_PATH+8,"%s\\%s",sysdir,*p);
lib=LoadLibrary(path);
@@ -132,7 +132,7 @@ namespace
if(!pfunc)
{
FreeLibrary(lib);
- lib=NULL;
+ lib=0;
continue;
}
p_getaddrinfo=reinterpret_cast<t_getaddrinfo>(pfunc);
@@ -140,8 +140,8 @@ namespace
if(!pfunc)
{
FreeLibrary(lib);
- lib=NULL;
- p_getaddrinfo=NULL;
+ lib=0;
+ p_getaddrinfo=0;
continue;
}
p_freeaddrinfo=reinterpret_cast<t_freeaddrinfo>(pfunc);
@@ -169,8 +169,8 @@ GIOChannelSocketSSL :: GIOChannelSocketSSL ():
_tag_watch (0),
_tag_timeout (0),
_listener (0),
- _out_buf (g_string_new (NULL)),
- _in_buf (g_string_new (NULL)),
+ _out_buf (g_string_new (0)),
+ _in_buf (g_string_new (0)),
_io_performed (false)
{
debug ("GIOChannelSocketSSL ctor " << (void*)this);
@@ -295,12 +295,12 @@ GIOChannelSocketSSL :: create_channel (const StringView& host_in, int port, std:
GIOChannel * channel (0);
#ifndef G_OS_WIN32
channel = g_io_channel_unix_new (sockfd);
- g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, 0);
#else
channel = g_io_channel_win32_new_socket (sockfd);
#endif
- if (g_io_channel_get_encoding (channel) != NULL)
- g_io_channel_set_encoding (channel, NULL, NULL);
+ if (g_io_channel_get_encoding (channel) != 0)
+ g_io_channel_set_encoding (channel, 0, 0);
g_io_channel_set_buffered (channel, true);
g_io_channel_set_line_term (channel, "\n", 1);
return ssl_get_iochannel(channel);
@@ -316,6 +316,63 @@ namespace
}
}
+namespace
+{
+
+ typedef struct
+ {
+ GIOChannel pad;
+ gint fd;
+ GIOChannel *giochan;
+ SSL *ssl;
+ SSL_CTX *ctx;
+ unsigned int verify:1;
+ } GIOSSLChannel;
+
+ static pthread_mutex_t *lock_cs;
+
+ void gio_lock(int mode, int type, const char *file, int line)
+ {
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock(&(lock_cs[type]));
+ else
+ pthread_mutex_unlock(&(lock_cs[type]));
+ }
+
+ void thread_setup(void) {
+
+ lock_cs = (pthread_mutex_t*)malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+ for (int i=0; i<CRYPTO_num_locks(); i++)
+ if (pthread_mutex_init(&(lock_cs[i]),0) != 0)
+ g_warning("error initialing mutex!");
+
+ // CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
+ CRYPTO_set_locking_callback(gio_lock);
+ }
+
+ void thread_cleanup(void) {
+
+ CRYPTO_set_locking_callback(0);
+ if (lock_cs)
+ {
+ for (int i=0; i<CRYPTO_num_locks(); i++)
+ if (&lock_cs[i]) pthread_mutex_destroy(&lock_cs[i]);
+ free(lock_cs);
+ }
+ }
+
+
+ void ssl_free(GIOChannel *handle)
+ {
+ GIOSSLChannel *chan = (GIOSSLChannel *)handle;
+ g_io_channel_unref(chan->giochan);
+ SSL_free(chan->ssl);
+ SSL_CTX_free(chan->ctx);
+ thread_cleanup();
+ g_free(chan);
+ }
+}
+
GIOChannelSocketSSL :: ~GIOChannelSocketSSL ()
{
//std::cerr << LINE_ID << " destroying socket " << this << std::endl;
@@ -323,11 +380,10 @@ GIOChannelSocketSSL :: ~GIOChannelSocketSSL ()
remove_source (_tag_watch);
remove_source (_tag_timeout);
-
if (_channel)
{
- g_io_channel_shutdown (_channel, true, NULL);
- g_io_channel_unref (_channel);
+ g_io_channel_shutdown (_channel, true, 0);
+ ssl_free(_channel);
_channel = 0;
}
@@ -371,15 +427,6 @@ GIOChannelSocketSSL :: write_command (const StringView& command, Listener * l)
namespace
{
- typedef struct
- {
- GIOChannel pad;
- gint fd;
- GIOChannel *giochan;
- SSL *ssl;
- SSL_CTX *ctx;
- unsigned int verify:1;
- } GIOSSLChannel;
SSL_CTX* ssl_init(void)
{
@@ -405,15 +452,6 @@ namespace
return G_IO_STATUS_ERROR;
}
- void ssl_free(GIOChannel *handle)
- {
- GIOSSLChannel *chan = (GIOSSLChannel *)handle;
- g_io_channel_unref(chan->giochan);
- SSL_free(chan->ssl);
- SSL_CTX_free(chan->ctx);
- g_free(chan);
- }
-
int ssl_handshake(GIOChannel *handle)
{
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
@@ -428,25 +466,27 @@ namespace
err = SSL_get_error(chan->ssl, ret);
if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
errstr = ERR_reason_error_string(ERR_get_error());
- g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "server closed connection");
+ g_warning("SSL handshake failed: %s", errstr != 0 ? errstr : "server closed connection");
return -1;
}
return err == SSL_ERROR_WANT_READ ? 1 : 3;
}
+
cert = SSL_get_peer_certificate(chan->ssl);
- if (cert == NULL) {
+ if (cert == 0) {
g_warning("SSL server supplied no certificate");
return -1;
}
-// ret = !chan->verify || ssl_verify(chan->ssl, chan->ctx, cert);
+
+// ret = chan->verify ? ssl_verify(chan->ssl, chan->ctx, handle->hostname.c_str(), cert) : true;
X509_free(cert);
return ret ? 0 : -1;
}
GIOStatus ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize *ret, GError **gerr)
{
- return G_IO_STATUS_AGAIN;
+ return G_IO_STATUS_NORMAL;
}
GIOStatus ssl_read_line_string(GIOChannel *handle, GString* g, gsize *ret, GError **gerr)
@@ -455,27 +495,22 @@ namespace
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
gint err;
- char tmp[4096];
+ size_t tmp_size(4096*128);
+ char tmp[tmp_size];
g_string_set_size(g,0);
- /// TODO perhaps own thread for this??
if (handle->read_buf->len == 0)
{
- err = SSL_read(chan->ssl, tmp, sizeof(tmp));
- if(err < 0)
+ err = SSL_read(chan->ssl, tmp, tmp_size*sizeof(char));
+ if (ret) *ret = err < 0 ? 0 : err;
+ if(err <= 0)
{
- if (ret) *ret = 0;
- if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) {
+ if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
return G_IO_STATUS_AGAIN;
- }
return ssl_errno(errno);
}
else
- {
- std::cerr<<"append len "<<err<<std::endl;
g_string_append_len (handle->read_buf,tmp,err);
- if (ret) *ret = err;
- }
}
//fill in from read_buf
@@ -582,15 +617,15 @@ GIOChannelSocketSSL :: do_read ()
while (more && !_abort_flag)
{
_io_performed = true;
- const GIOStatus status (ssl_read_line_string(_channel, g, NULL, &err));
- //g_io_channel_read_line_string (_channel, g, NULL, &err));
+ gsize ret;
+ const GIOStatus status (ssl_read_line_string(_channel, g, &ret, &err));
if (status == G_IO_STATUS_NORMAL)
{
g_string_prepend_len (g, _partial_read.c_str(), _partial_read.size());
_partial_read.clear ();
- debug_v ("read [" << g->str << "]"); // verbose debug, if --debug --debug was on the command-line
+ debug_v ("read [" << g->str << "]");
increment_xfer_byte_count (g->len);
if (g_str_has_suffix (g->str, "\r\n"))
g_string_truncate (g, g->len-2);
@@ -599,10 +634,11 @@ GIOChannelSocketSSL :: do_read ()
else if (status == G_IO_STATUS_AGAIN)
{
// see if we've got a partial line buffered up
- if (_channel->read_buf) {
+ if (_channel->read_buf->len != 0) {
+ increment_xfer_byte_count ((int)ret);
_partial_read.append (_channel->read_buf->str, _channel->read_buf->len);
- std::cerr<<"partial read : "<<_partial_read<<std::endl;
g_string_set_size (_channel->read_buf, 0);
+// std::cerr<<"partial read : "<<_partial_read<<"("<<_channel->read_buf->len<<"/"<<_partial_read.size()<<")\n";
}
return IO_READ;
}
@@ -610,7 +646,7 @@ GIOChannelSocketSSL :: do_read ()
{
const char * msg (err ? err->message : _("Unknown Error"));
Log::add_err_va (_("Error reading from %s: %s"), _host.c_str(), msg);
- if (err != NULL)
+ if (err != 0)
g_clear_error (&err);
return IO_ERR;
}
@@ -762,73 +798,30 @@ GIOChannelSocketSSL :: set_watch_mode (WatchMode mode)
GIOChannel *
-GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, const char *mycert, const char *mypkey, const char *cafile, const char *capath, gboolean verify)
+GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, gboolean verify)
{
- GIOSSLChannel *chan;
- GIOChannel *gchan;
- int err, fd;
- SSL *ssl;
- SSL_CTX *ctx;
+ GIOSSLChannel *chan(0);
+ GIOChannel *gchan(0);
+ int err(0), fd(0);
+ SSL *ssl(0);
+ SSL_CTX *ctx(0);
- g_return_val_if_fail(handle != NULL, NULL);
+ g_return_val_if_fail(handle != 0, 0);
if(!(ctx = ssl_init()))
- return NULL;
+ return 0;
if(!(fd = g_io_channel_unix_get_fd(handle)))
- return NULL;
-
- ///TODO cert validation !
-// if (mycert && *mycert) {
-// char *scert = NULL, *spkey = NULL;
-// if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
-// g_error("Could not allocate memory for SSL context");
-// return NULL;
-// }
-// scert = convert_home(mycert);
-// if (mypkey && *mypkey)
-// spkey = convert_home(mypkey);
-// if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM))
-// g_warning("Loading of client certificate '%s' failed", mycert);
-// else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM))
-// g_warning("Loading of private key '%s' failed", mypkey ? mypkey : mycert);
-// else if (! SSL_CTX_check_private_key(ctx))
-// g_warning("Private key does not match the certificate");
-// g_free(scert);
-// g_free(spkey);
-// }
-
-// if ((cafile && *cafile) || (capath && *capath)) {
-// char *scafile = NULL;
-// char *scapath = NULL;
-// if (! ctx && (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
-// g_error("Could not allocate memory for SSL context");
-// return NULL;
-// }
-// if (cafile && *cafile)
-// scafile = convert_home(cafile);
-// if (capath && *capath)
-// scapath = convert_home(capath);
-// if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) {
-// g_warning("Could not load CA list for verifying SSL server certificate");
-// g_free(scafile);
-// g_free(scapath);
-// SSL_CTX_free(ctx);
-// return NULL;
-// }
-// g_free(scafile);
-// g_free(scapath);
-// verify = TRUE;
-// }
-
-// if (ctx == NULL)
-// ctx = ssl_ctx;
+ {
+ if (ctx) SSL_CTX_free(ctx);
+ return 0;
+ }
if(!(ssl = SSL_new(ctx)))
{
SSL_CTX_free(ctx);
g_warning("Failed to allocate SSL structure");
- return NULL;
+ return 0;
}
if(!(err = SSL_set_fd(ssl, fd)))
@@ -836,9 +829,11 @@ GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, const char *mycert,
g_warning("Failed to associate socket to SSL stream");
SSL_free(ssl);
SSL_CTX_free(ctx);
- return NULL;
+ return 0;
}
+ thread_setup();
+
chan = g_new0(GIOSSLChannel, 1);
chan->fd = fd;
chan->giochan = handle;
@@ -851,9 +846,12 @@ GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, const char *mycert,
g_io_channel_init(gchan);
gchan->read_buf = g_string_sized_new(4096*128);
+ /// FIXME : callback
+ debug("before handshake");
while (ssl_handshake(gchan) != 0) ;
+ debug("after handshake");
- std::cerr<<"handshake success!\n";
+// std::cerr<<"handshake success!\n";
return gchan;
}
diff --git a/pan/tasks/socket-impl-openssl.h b/pan/tasks/socket-impl-openssl.h
index 6bec184..323e76f 100644
--- a/pan/tasks/socket-impl-openssl.h
+++ b/pan/tasks/socket-impl-openssl.h
@@ -27,6 +27,7 @@
#include <openssl/crypto.h>
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -72,8 +73,7 @@ namespace pan
//SSL functions
private:
- GIOChannel* ssl_get_iochannel(GIOChannel *handle, const char *mycert=NULL, const char *mypkey=NULL,
- const char *cafile=NULL, const char *capath=NULL, gboolean verify=false);
+ GIOChannel* ssl_get_iochannel(GIOChannel *handle, gboolean verify=true);
public:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]