diff -up bitlbee-3.0/configure.nss bitlbee-3.0/configure
--- bitlbee-3.0/configure.nss 2010-11-22 13:36:02.000000000 +0100
+++ bitlbee-3.0/configure 2010-11-22 13:36:12.000000000 +0100
@@ -290,10 +291,10 @@ EOF
detect_nss()
{
- if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG mozilla-nss; then
+ if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG nss; then
cat<<EOF>>Makefile.settings
-EFLAGS+=`$PKG_CONFIG --libs mozilla-nss`
-CFLAGS+=`$PKG_CONFIG --cflags mozilla-nss`
+EFLAGS+=`$PKG_CONFIG --libs nss`
+CFLAGS+=`$PKG_CONFIG --cflags nss`
EOF
ssl=nss
diff -up bitlbee-3.0/lib/ssl_nss.c.nss bitlbee-3.0/lib/ssl_nss.c
--- bitlbee-3.0/lib/ssl_nss.c.nss 2010-10-22 02:51:31.000000000 +0200
+++ bitlbee-3.0/lib/ssl_nss.c 2010-11-22 13:35:48.000000000 +0100
@@ -33,8 +33,10 @@
#include <prio.h>
#include <sslproto.h>
#include <nss.h>
+#include <pk11pub.h>
#include <private/pprio.h>
#include <ssl.h>
+#include <seccomon.h>
#include <secerr.h>
#include <sslerr.h>
@@ -52,6 +54,7 @@ struct scd
};
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
+static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond );
static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver)
@@ -121,6 +124,35 @@ void *ssl_connect( char *host, int port,
return( conn );
}
+static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond )
+{
+ struct scd *conn = data;
+
+ return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
+}
+
+void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+{
+ struct scd *conn = g_new0( struct scd, 1 );
+
+ conn->fd = fd;
+ conn->func = func;
+ conn->data = data;
+
+ /* This function should be called via a (short) timeout instead of
+ directly from here, because these SSL calls are *supposed* to be
+ *completely* asynchronous and not ready yet when this function
+ (or *_connect, for examle) returns. Also, errors are reported via
+ the callback function, not via this function's return value.
+
+ In short, doing things like this makes the rest of the code a lot
+ simpler. */
+
+ b_timeout_add( 1, ssl_starttls_real, conn );
+
+ return conn;
+}
+
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
{
struct scd *conn = data;
@@ -200,3 +232,94 @@ b_input_condition ssl_getdirection( void
/* Just in case someone calls us, let's return the most likely case: */
return B_EV_IO_READ;
}
+
+#if 0
+size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len,
+ const unsigned char *input, size_t input_len, const unsigned char *iv,
+ unsigned char **res)
+{
+ int output_length = 0;
+
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* SymKey = NULL;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECItem keyItem, ivItem;
+ SECStatus rv1, rv2;
+ int tmp1_outlen, tmp2_outlen;
+
+ if (!initialized)
+ {
+ ssl_init();
+ }
+
+ *res = g_new0(unsigned char, 1024);
+
+ cipherMech = CKM_DES3_CBC_PAD;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+
+ if (slot == NULL)
+ {
+ fprintf(stderr, "Unable to find security device (err %d)\n",
+ PR_GetError());
+ goto out;
+ }
+
+ // Converts "raw key" into a key object.
+ keyItem.type = siBuffer;
+ keyItem.data = (unsigned char*)key;
+ keyItem.len = key_len;
+
+ SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT,
+ &keyItem, NULL);
+
+ if (SymKey == NULL)
+ {
+ fprintf(stderr, "Failure to import key into NSS (err %d)\n",
+ PR_GetError());
+ goto out;
+ }
+
+ /* set up the PKCS11 encryption paramters.
+ * when not using CBC mode, ivItem.data and ivItem.len can be 0, or you
+ * can simply pass NULL for the iv parameter in PK11_ParamFromIV func
+ */
+ ivItem.type = siBuffer;
+ ivItem.data = iv;
+ ivItem.len = strlen(iv); // ??? Is it right? FIXME
+ SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
+ if (SecParam == NULL)
+ {
+ fprintf(stderr, "Failure to set up PKCS11 param (err %d)\n",
+ PR_GetError());
+ goto out;
+ }
+
+ /* ========================= START SECTION ============================= */
+ /* If using the the same key and iv over and over, stuff before this */
+ /* section and after this section needs to be done only ONCE */
+ /* ENCRYPT data into buf1. buf1 len must be atleast (data len + 8) */
+ tmp1_outlen = tmp2_outlen = 0;
+
+ /* Create cipher context */
+ EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT,
+ SymKey, SecParam);
+ rv1 = PK11_CipherOp(EncContext, res, &tmp1_outlen, sizeof(res),
+ input, input_len+1);
+ rv2 = PK11_DigestFinal(EncContext, res+tmp1_outlen, &tmp2_outlen,
+ sizeof(res)-tmp1_outlen);
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ output_length = tmp1_outlen + tmp2_outlen;
+ if (rv1 != SECSuccess || rv2 != SECSuccess)
+ goto out;
+
+ return output_length;
+
+ out:
+ if (SymKey)
+ PK11_FreeSymKey(SymKey);
+ if (SecParam)
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+}
+#endif