From: "Luis R. Rodriguez" <[email protected]>

irssi supports letting you specify the client SSL password
using the ssl_pass primitive on the configuration file. Its
a terrible idea to be putting passwords on unencrypted files
though so some security rational folks won't ever want to
do this. If you currently don't supply one irssi goes on and
assumes you do not want to use it, and depending on the server
configuration it may or not fail on the SSL handshake and not
allow any connection to go through... Freenode lets you
authenticate your username with an SSL client certificate
so this is not desirable behavior.

This adds support to irrsi so that if an SSL client
certificate was supplied and if no password was set we prompt
the user for one.

Upon disconnects we won't have to re-enter the password but
just in case for whatever reason SSL needs it we redraw the
screen to the console screen should the user have to enter
a password again. Users that do not have a password on the
SSL client certificate can just either enter an empty
password upon the prompt or set an empty password on the
configuration file. Its a bad idea to be using passwordless
client certificate files anyway, so let them do a bit more
work.

We only prompt for a password if and only if the client
certificate was set, if you have different client certificate
files or use the client certificate for different connections
you'll be asked for a password for each server SSL connection.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
 src/core/network-openssl.c | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c
index 768fd54..23258c6 100644
--- a/src/core/network-openssl.c
+++ b/src/core/network-openssl.c
@@ -37,6 +37,8 @@
 #include <validator/val_dane.h>
 #endif
 
+void window_console(void);
+
 /* ssl i/o channel object */
 typedef struct
 {
@@ -434,6 +436,7 @@ static int get_pem_password_callback(char *buffer, int 
max_length, int rwflag, v
        char *password;
        size_t length;
 
+       /* should not happen but better leave it */
        if (pass == NULL)
                return 0;
 
@@ -447,6 +450,35 @@ static int get_pem_password_callback(char *buffer, int 
max_length, int rwflag, v
        return length;
 }
 
+static int prompt_pem_password_callback(char *buffer, int max_length, int 
rwflag, void *pem_cert)
+{
+       char *password, prompt[256];
+       size_t length;
+
+       window_console();
+
+       /* should not happen but better leave it */
+       if (pem_cert == NULL)
+               return 0;
+
+       snprintf(prompt, 256, "Enter Passphrase for %s:", (char *) pem_cert);
+       password = getpass(prompt);
+
+       if (!password)
+               return 0;
+
+       length = strlen(password);
+
+       if (length > max_length)
+               return 0;
+
+       strncpy(buffer, password, length);
+       irssi_redraw();
+
+       return length;
+}
+
+
 static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, 
SERVER_REC *server)
 {
        GIOSSLChannel *chan;
@@ -476,8 +508,13 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel 
*handle, int port, SERVER_
                return NULL;
        }
        SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
-       SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback);
-       SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass);
+       if (mypass) {
+               SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback);
+               SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass);
+       } else if (mycert && *mycert) {
+               SSL_CTX_set_default_passwd_cb(ctx, 
prompt_pem_password_callback);
+               SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mycert);
+       }
 
        if (mycert && *mycert) {
                char *scert = NULL, *spkey = NULL;
-- 
2.0.3


Reply via email to