$OpenBSD: patch-src_core_network-openssl_c,v 1.4 2011/11/16 10:16:57 sthen Exp $
--- src/core/network-openssl.c.orig	Sun Nov  6 04:52:49 2011
+++ src/core/network-openssl.c	Sun Nov  6 05:11:41 2011
@@ -43,6 +43,8 @@ typedef struct
 	const char *hostname;
 } GIOSSLChannel;
 
+void irssi_redraw(void);
+
 static int ssl_inited = FALSE;
 
 static void irssi_ssl_free(GIOChannel *handle)
@@ -97,28 +99,28 @@ static char *tls_text_name(X509_NAME *name, int nid)
 
 	if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) {
 		return NULL;
-    }
+	}
 
-    entry = X509_NAME_get_entry(name, pos);
-    g_return_val_if_fail(entry != NULL, NULL);
-    entry_str = X509_NAME_ENTRY_get_data(entry);
-    g_return_val_if_fail(entry_str != NULL, NULL);
+	entry = X509_NAME_get_entry(name, pos);
+	g_return_val_if_fail(entry != NULL, NULL);
+	entry_str = X509_NAME_ENTRY_get_data(entry);
+	g_return_val_if_fail(entry_str != NULL, NULL);
 
-    /* Convert everything into UTF-8. It's up to OpenSSL to do something
+	/* Convert everything into UTF-8. It's up to OpenSSL to do something
 	   reasonable when converting ASCII formats that contain non-ASCII
 	   content. */
-    if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_str)) < 0) {
-    	g_warning("Error decoding ASN.1 type=%d", ASN1_STRING_type(entry_str));
-    	return NULL;
-    }
+	if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_str)) < 0) {
+		g_warning("Error decoding ASN.1 type=%d", ASN1_STRING_type(entry_str));
+		return NULL;
+	}
 
-    if (has_internal_nul((char *)utf8_value, utf8_length)) {
-    	g_warning("NUL character in hostname in certificate");
-    	OPENSSL_free(utf8_value);
-    	return NULL;
-    }
+	if (has_internal_nul((char *)utf8_value, utf8_length)) {
+		g_warning("NUL character in hostname in certificate");
+		OPENSSL_free(utf8_value);
+		return NULL;
+	}
 
-    result = g_strdup((char *) utf8_value);
+	result = g_strdup((char *) utf8_value);
 	OPENSSL_free(utf8_value);
 	return result;
 }
@@ -168,10 +170,10 @@ static gboolean irssi_ssl_verify_hostname(X509 *cert, 
 			if (cert_dns_name && *cert_dns_name) {
 				matched = match_hostname(cert_dns_name, hostname);
 			}
-    	}
+		}
 
-	    /* Free stack *and* member GENERAL_NAME objects */
-	    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+		/* Free stack *and* member GENERAL_NAME objects */
+		sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
 	}
 
 	if (has_dns_name) {
@@ -182,15 +184,15 @@ static gboolean irssi_ssl_verify_hostname(X509 *cert, 
 		return matched;
 	} else { /* No subjectAltNames, look at CommonName */
 		cert_subject_cn = tls_text_name(X509_get_subject_name(cert), NID_commonName);
-	    if (cert_subject_cn && *cert_subject_cn) {
-	    	matched = match_hostname(cert_subject_cn, hostname);
-	    	if (! matched) {
+		if (cert_subject_cn && *cert_subject_cn) {
+			matched = match_hostname(cert_subject_cn, hostname);
+			if (! matched) {
 				g_warning("SSL certificate common name '%s' doesn't match host name '%s'", cert_subject_cn, hostname);
-	    	}
-	    } else {
-	    	g_warning("No subjectAltNames and no valid common name in certificate");
-	    }
-	    free(cert_subject_cn);
+			}
+		} else {
+			g_warning("No subjectAltNames and no valid common name in certificate");
+		}
+		free(cert_subject_cn);
 	}
 
 	return matched;
@@ -247,6 +249,7 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gc
 	GIOSSLChannel *chan = (GIOSSLChannel *)handle;
 	gint ret1, err;
 	const char *errstr;
+	gchar *errmsg;
 
 	ret1 = SSL_read(chan->ssl, buf, len);
 	if(ret1 <= 0)
@@ -271,9 +274,10 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gc
 			if (errstr == NULL)
 				errstr = "unknown SSL error";
 		}
-		g_warning("SSL read error: %s", errstr);
+		errmsg = g_strdup_printf("SSL read error: %s", errstr);
 		*gerr = g_error_new_literal(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
-					    errstr);
+					    errmsg);
+		g_free(errmsg);
 		return G_IO_STATUS_ERROR;
 	}
 	else
@@ -290,6 +294,7 @@ static GIOStatus irssi_ssl_write(GIOChannel *handle, c
 	GIOSSLChannel *chan = (GIOSSLChannel *)handle;
 	gint ret1, err;
 	const char *errstr;
+	gchar *errmsg;
 
 	ret1 = SSL_write(chan->ssl, (const char *)buf, len);
 	if(ret1 <= 0)
@@ -314,9 +319,10 @@ static GIOStatus irssi_ssl_write(GIOChannel *handle, c
 			if (errstr == NULL)
 				errstr = "unknown SSL error";
 		}
-		g_warning("SSL write error: %s", errstr);
+		errmsg = g_strdup_printf("SSL write error: %s", errstr);
 		*gerr = g_error_new_literal(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
-					    errstr);
+					    errmsg);
+		g_free(errmsg);
 		return G_IO_STATUS_ERROR;
 	}
 	else
@@ -374,6 +380,17 @@ static GIOFuncs irssi_ssl_channel_funcs = {
     irssi_ssl_get_flags
 };
 
+static int getpass_cb(char *buf, int size, int rwflag, void *keyname)
+{
+	char *pp, prompt[256];
+	snprintf(prompt, 256, "Enter Passphrase for %s:", keyname);
+	pp = getpass(prompt);
+	strncpy(buf, pp, size);
+	buf[size - 1] = '\0';
+	irssi_redraw();
+	return(strlen(buf));
+}
+
 static gboolean irssi_ssl_init(void)
 {
 	SSL_library_init();
@@ -406,12 +423,15 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel 
 		g_error("Could not allocate memory for SSL context");
 		return NULL;
 	}
+	SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
 
 	if (mycert && *mycert) {
 		char *scert = NULL, *spkey = NULL;
 		scert = convert_home(mycert);
 		if (mypkey && *mypkey)
 			spkey = convert_home(mypkey);
+		SSL_CTX_set_default_passwd_cb(ctx, getpass_cb);
+		SSL_CTX_set_default_passwd_cb_userdata(ctx, mypkey ? mypkey : mycert);
 		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))
