2003-12-15 Mikael Hallendal <micke@imendio.com>
* loudmouth/lm-connection.c:
- Fixed issue with the SSL parts. Patch from Colin Walters
--- a/ChangeLog Thu Nov 27 21:12:51 2003 +0000
+++ b/ChangeLog Mon Dec 15 16:21:28 2003 +0000
@@ -1,3 +1,8 @@
+2003-12-15 Mikael Hallendal <micke@imendio.com>
+
+ * loudmouth/lm-connection.c:
+ - Fixed issue with the SSL parts. Patch from Colin Walters
+
2003-11-20 Ross Burton <ross@burtonini.com>
* loudmouth/lm-message-node.h:
--- a/docs/reference/tmpl/lm-connection.sgml Thu Nov 27 21:12:51 2003 +0000
+++ b/docs/reference/tmpl/lm-connection.sgml Mon Dec 15 16:21:28 2003 +0000
@@ -232,15 +232,6 @@
@Returns:
-<!-- ##### FUNCTION lm_connection_set_use_ssl ##### -->
-<para>
-
-</para>
-
-@connection:
-@use_ssl:
-
-
<!-- ##### FUNCTION lm_connection_send ##### -->
<para>
--- a/docs/reference/tmpl/loudmouth-unused.sgml Thu Nov 27 21:12:51 2003 +0000
+++ b/docs/reference/tmpl/loudmouth-unused.sgml Mon Dec 15 16:21:28 2003 +0000
@@ -27,6 +27,14 @@
@value:
@user_data:
+<!-- ##### FUNCTION lm_connection_set_use_ssl ##### -->
+<para>
+
+</para>
+
+@connection:
+@use_ssl:
+
<!-- ##### FUNCTION lm_message_node_add_child_message_node ##### -->
<para>
--- a/loudmouth/lm-connection.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-connection.c Mon Dec 15 16:21:28 2003 +0000
@@ -2,7 +2,6 @@
/*
* Copyright (C) 2003 Imendio HB
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
@@ -63,6 +62,7 @@
gchar *server;
guint port;
gboolean use_ssl;
+ char fingerprint[20];
#ifdef HAVE_GNUTLS
gnutls_session gnutls_session;
@@ -112,10 +112,13 @@
static void connection_new_message_cb (LmParser *parser,
LmMessage *message,
LmConnection *connection);
-static gboolean connection_do_open (LmConnection *connection,
- GError **error);
+static gboolean connection_do_open (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_func,
+ gpointer user_data,
+ GError **error);
-static void connection_do_close (LmConnection *connection);
+static void connection_do_close (LmConnection *connection);
static gboolean connection_in_event (GIOChannel *source,
GIOCondition condition,
LmConnection *connection);
@@ -254,8 +257,94 @@
lm_queue_push_tail (connection->incoming_messages, m);
}
+#ifdef HAVE_GNUTLS
static gboolean
-connection_do_open (LmConnection *connection, GError **error)
+connection_verify_certificate (LmConnection *connection,
+ const gchar *expected_fingerprint,
+ LmSSLFunction ssl_function,
+ gpointer user_data)
+{
+ int status;
+
+ /* This verification function uses the trusted CAs in the credentials
+ * structure. So you must have installed one or more CA certificates.
+ */
+ status = gnutls_certificate_verify_peers (connection->gnutls_session);
+
+ if (status == GNUTLS_E_NO_CERTIFICATE_FOUND)
+ if (ssl_function (connection,
+ LM_SSL_STATUS_NO_CERT_FOUND,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+
+ if (status & GNUTLS_CERT_INVALID
+ || status & GNUTLS_CERT_NOT_TRUSTED
+ || status & GNUTLS_CERT_CORRUPTED
+ || status & GNUTLS_CERT_REVOKED)
+ if (ssl_function (connection,
+ LM_SSL_STATUS_UNTRUSTED_CERT,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+
+ if (gnutls_certificate_expiration_time_peers (connection->gnutls_session) < time (0)) {
+ if (ssl_function (connection,
+ LM_SSL_STATUS_CERT_EXPIRED,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ }
+
+ if (gnutls_certificate_activation_time_peers (connection->gnutls_session) > time (0)) {
+ if (ssl_function (connection,
+ LM_SSL_STATUS_CERT_NOT_ACTIVATED,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ }
+
+ if (gnutls_certificate_type_get (connection->gnutls_session) == GNUTLS_CRT_X509) {
+ const gnutls_datum* cert_list;
+ int cert_list_size;
+ int digest_size;
+
+ cert_list = gnutls_certificate_get_peers (connection->gnutls_session, &cert_list_size);
+ if (cert_list == NULL) {
+ if (ssl_function (connection,
+ LM_SSL_STATUS_NO_CERT_FOUND,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ }
+ if (!gnutls_x509_check_certificates_hostname (&cert_list[0],
+ connection->server)) {
+ if (ssl_function (connection,
+ LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ }
+ if (gnutls_x509_fingerprint (GNUTLS_DIG_MD5, &cert_list[0],
+ connection->fingerprint,
+ &digest_size) >= 0) {
+ if (expected_fingerprint &&
+ memcmp (expected_fingerprint, connection->fingerprint,
+ digest_size) &&
+ ssl_function (connection,
+ LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ } else if (ssl_function (connection,
+ LM_SSL_STATUS_GENERIC_ERROR,
+ user_data) != LM_SSL_RESPONSE_CONTINUE)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+connection_do_open (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_function,
+ gpointer user_data,
+ GError **error)
{
gint fd = -1;
int err = -1;
@@ -333,6 +422,7 @@
#ifdef HAVE_GNUTLS
if (connection->use_ssl) {
int ret;
+ gboolean auth_ok = TRUE;
const int cert_type_priority[2] =
{ GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP };
@@ -348,14 +438,32 @@
(gnutls_transport_ptr) fd);
ret = gnutls_handshake (connection->gnutls_session);
+
+ if (ret >= 0) {
+ auth_ok = connection_verify_certificate (connection,
+ fingerprint,
+ ssl_function,
+ user_data);
+ }
- if (ret < 0) {
+ if (ret < 0 || !auth_ok) {
+ char *errmsg;
+
gnutls_perror (ret);
shutdown (fd, SHUT_RDWR);
close (fd);
connection_do_close (connection);
- g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
- "*** GNUTLS handshake failed");
+
+ if (!auth_ok) {
+ errmsg = "*** GNUTLS authentication error";
+ } else {
+ errmsg = "*** GNUTLS handshake failed";
+ }
+
+ g_set_error (error,
+ LM_ERROR, LM_ERROR_CONNECTION_OPEN,
+ errmsg);
+
return FALSE;
}
}
@@ -878,6 +986,7 @@
connection->port = LM_CONNECTION_DEFAULT_PORT;
connection->use_ssl = FALSE;
+ connection->fingerprint[0] = '\0';
connection->disconnect_cb = NULL;
connection->incoming_messages = lm_queue_new ();
@@ -900,8 +1009,10 @@
}
/**
- * lm_connection_open:
- * @connection: #LmConnection to open
+ * lm_connection_open_ssl:
+ * @connection: #LmConnection to open, using SSL
+ * @fingerprint: the expected fingerprint of the remote cert, or %NULL
+ * @ssl_function: Callback function used when an authentication error occurs.
* @function: Callback function that will be called when the connection is open.
* @user_data: User data that will be passed to @function.
* @notify: Function for freeing that user_data, can be NULL.
@@ -912,16 +1023,20 @@
* Return value: #TRUE if everything went fine, otherwise #FALSE.
**/
gboolean
-lm_connection_open (LmConnection *connection,
- LmResultFunction function,
- gpointer user_data,
- GDestroyNotify notify,
- GError **error)
+lm_connection_open_ssl (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_function,
+ LmResultFunction function,
+ gpointer user_data,
+ GDestroyNotify notify,
+ GError **error)
{
LmMessage *m;
gboolean result;
g_return_val_if_fail (connection != NULL, FALSE);
+
+ connection->use_ssl = ssl_function != NULL;
if (lm_connection_is_open (connection)) {
g_set_error (error,
@@ -946,7 +1061,7 @@
lm_verbose ("Connecting to: %s:%d\n",
connection->server, connection->port);
- if (!connection_do_open (connection, error)) {
+ if (!connection_do_open (connection, fingerprint, ssl_function, user_data, error)) {
return FALSE;
}
@@ -965,8 +1080,34 @@
}
/**
- * lm_connection_open_and_block:
- * @connection: an #LmConnection
+ * lm_connection_open:
+ * @connection: #LmConnection to open
+ * @function: Callback function that will be called when the connection is open.
+ * @user_data: User data that will be passed to @function.
+ * @notify: Function for freeing that user_data, can be NULL.
+ * @error: location to store error, or %NULL
+ *
+ * An async call to open @connection. When the connection is open @function will be called.
+ *
+ * Return value: #TRUE if everything went fine, otherwise #FALSE.
+ **/
+gboolean
+lm_connection_open (LmConnection *connection,
+ LmResultFunction function,
+ gpointer user_data,
+ GDestroyNotify notify,
+ GError **error)
+{
+ return lm_connection_open_ssl (connection, NULL, NULL,
+ function, user_data, notify, error);
+}
+
+/**
+ * lm_connection_open_and_block_ssl:
+ * @connection: an #LmConnection to open using SSL
+ * @fingerprint: the expected fingerprint of the remote cert, or %NULL
+ * @ssl_function: Callback function used when a SSL error occurs.
+ * @user_data: User data that will be passed to @function.
* @error: location to store error, or %NULL
*
* Opens @connection and waits until the stream is setup.
@@ -974,7 +1115,11 @@
* Return value: #TRUE if no errors where encountered during opening and stream setup successfully, #FALSE otherwise.
**/
gboolean
-lm_connection_open_and_block (LmConnection *connection, GError **error)
+lm_connection_open_and_block_ssl (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_function,
+ gpointer user_data,
+ GError **error)
{
LmMessage *m;
gboolean result;
@@ -982,6 +1127,8 @@
gboolean ret_val = FALSE;
g_return_val_if_fail (connection != NULL, FALSE);
+
+ connection->use_ssl = ssl_function != NULL;
if (lm_connection_is_open (connection)) {
g_set_error (error,
@@ -1001,7 +1148,8 @@
lm_verbose ("(Block)Connecting to: %s:%d\n",
connection->server, connection->port);
- if (!connection_do_open (connection, error)) {
+ if (!connection_do_open (connection, fingerprint, ssl_function,
+ user_data, error)) {
return FALSE;
}
@@ -1051,6 +1199,22 @@
}
/**
+ * lm_connection_open_and_block:
+ * @connection: an #LmConnection to open
+ * @error: location to store error, or %NULL
+ *
+ * Opens @connection and waits until the stream is setup.
+ *
+ * Return value: #TRUE if no errors where encountered during opening and stream setup successfully, #FALSE otherwise.
+ **/
+gboolean
+lm_connection_open_and_block (LmConnection *connection,
+ GError **error)
+{
+ return lm_connection_open_and_block_ssl (connection, NULL, NULL, NULL, error);
+}
+
+/**
* lm_connection_close:
* @connection: #LmConnection to close
* @error: location to store error, or %NULL
@@ -1360,21 +1524,17 @@
}
/**
- * lm_connection_set_use_ssl:
+ * lm_connection_get_fingerprint:
* @connection: an #LmConnection
- * @use_ssl: whether to use SSL or not.
+ *
+ * Returns the MD5 fingerprint of the remote server's certificate.
*
- * Sets whether @connection should use SSL for encrypting traffic to/from the server.
+ * Return value: A 16-byte array representing the fingerprint or %NULL if unknown.
**/
-void
-lm_connection_set_use_ssl (LmConnection *connection, gboolean use_ssl)
+const unsigned char *
+lm_connection_get_fingerprint (LmConnection *connection)
{
- if (lm_connection_is_open (connection)) {
- g_warning ("use_ssl can't be changed while connected");
- return;
- }
-
- connection->use_ssl = use_ssl;
+ return (unsigned char*) connection->fingerprint;
}
/**
--- a/loudmouth/lm-connection.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-connection.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
@@ -56,13 +55,38 @@
LM_DISCONNECT_REASON_UNKNOWN
} LmDisconnectReason;
-typedef void (* LmResultFunction) (LmConnection *connection,
- gboolean success,
- gpointer user_data);
+typedef enum {
+ LM_CERT_INVALID,
+ LM_CERT_ISSUER_NOT_FOUND,
+ LM_CERT_REVOKED,
+} LmCertificateStatus;
+
+typedef enum {
+ LM_SSL_STATUS_NO_CERT_FOUND,
+ LM_SSL_STATUS_UNTRUSTED_CERT,
+ LM_SSL_STATUS_CERT_EXPIRED,
+ LM_SSL_STATUS_CERT_NOT_ACTIVATED,
+ LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
+ LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
+ LM_SSL_STATUS_GENERIC_ERROR,
+} LmSSLStatus;
-typedef void (* LmDisconnectFunction) (LmConnection *connection,
- LmDisconnectReason reason,
- gpointer user_data);
+typedef enum {
+ LM_SSL_RESPONSE_CONTINUE,
+ LM_SSL_RESPONSE_STOP,
+} LmSSLResponse;
+
+typedef void (* LmResultFunction) (LmConnection *connection,
+ gboolean success,
+ gpointer user_data);
+
+typedef void (* LmDisconnectFunction) (LmConnection *connection,
+ LmDisconnectReason reason,
+ gpointer user_data);
+
+typedef LmSSLResponse (* LmSSLFunction) (LmConnection *connection,
+ LmSSLStatus status,
+ gpointer user_data);
LmConnection *lm_connection_new (const gchar *server);
@@ -71,9 +95,23 @@
gpointer user_data,
GDestroyNotify notify,
GError **error);
+gboolean lm_connection_open_ssl (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_function,
+ LmResultFunction function,
+ gpointer user_data,
+ GDestroyNotify notify,
+ GError **error);
+
gboolean lm_connection_open_and_block (LmConnection *connection,
GError **error);
+gboolean lm_connection_open_and_block_ssl (LmConnection *connection,
+ const gchar *fingerprint,
+ LmSSLFunction ssl_function,
+ gpointer user_data,
+ GError **error);
+
gboolean lm_connection_close (LmConnection *connection,
GError **error);
gboolean lm_connection_authenticate (LmConnection *connection,
@@ -102,8 +140,9 @@
guint port);
gboolean lm_connection_supports_ssl (void);
gboolean lm_connection_get_use_ssl (LmConnection *connection);
-void lm_connection_set_use_ssl (LmConnection *connection,
- gboolean use_ssl);
+
+const unsigned char *
+lm_connection_get_fingerprint (LmConnection *connection);
gboolean lm_connection_send (LmConnection *connection,
LmMessage *message,
--- a/loudmouth/lm-debug.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-debug.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-debug.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-debug.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-error.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-error.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-error.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-error.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-internals.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-internals.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message-handler.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message-handler.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message-handler.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message-handler.h Mon Dec 15 16:21:28 2003 +0000
@@ -2,7 +2,6 @@
/*
* Copyright (C) 2003 Imendio HB
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message-node.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message-node.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message-node.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message-node.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-message.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-message.h Mon Dec 15 16:21:28 2003 +0000
@@ -2,7 +2,6 @@
/*
* Copyright (C) 2003 Imendio HB
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-parser.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-parser.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-parser.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-parser.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-sha.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-sha.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-utils.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-utils.c Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/lm-utils.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/lm-utils.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/loudmouth.h Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/loudmouth.h Mon Dec 15 16:21:28 2003 +0000
@@ -1,7 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
--- a/loudmouth/test-lm.c Thu Nov 27 21:12:51 2003 +0000
+++ b/loudmouth/test-lm.c Mon Dec 15 16:21:28 2003 +0000
@@ -2,7 +2,6 @@
/*
* Copyright (C) 2003 Imendio HB
* Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- * Copyright (C) 2003 CodeFactory AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
@@ -24,19 +23,67 @@
#include <glib.h>
#include <string.h>
+#include <stdlib.h>
#include <loudmouth/loudmouth.h>
#ifdef __WIN32__
#include <winsock2.h>
#endif
#include "lm-internals.h"
-#define USAGE "Usage: test-lm <server> <username> <password>\n"
-
typedef struct {
gchar *name;
gchar *passwd;
} UserInfo;
+static unsigned char expected_fingerprint[20];
+
+static void
+print_finger (const unsigned char *fpr, unsigned int size)
+{
+ gint i;
+ for (i = 0; i < size-1; i++)
+ g_print ("%02X:", (unsigned char) fpr[i]);
+ g_print ("%02X", (unsigned char) fpr[size-1]);
+}
+
+static LmSSLResponse
+ssl_cb (LmConnection *connection, LmSSLStatus status, gpointer ud)
+{
+ g_print ("SSL status: %d\n", status);
+ switch (status) {
+ case LM_SSL_STATUS_NO_CERT_FOUND:
+ g_print ("No certificate found!\n");
+ break;
+ case LM_SSL_STATUS_UNTRUSTED_CERT:
+ g_print ("Certificate is not trusted!\n");
+ break;
+ case LM_SSL_STATUS_CERT_EXPIRED:
+ g_print ("Certificate has expired!\n");
+ break;
+ case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
+ g_print ("Certificate has not been activated!\n");
+ break;
+ case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
+ g_print ("Certificate hostname does not match expected hostname!\n");
+ break;
+ case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
+ const unsigned char *fpr = lm_connection_get_fingerprint (connection);
+ g_print ("Certificate fingerprint does not match expected fingerprint!\n");
+ g_print ("Remote fingerprint: ");
+ print_finger (fpr, 16);
+ g_print ("\nExpected fingerprint: ");
+ print_finger (expected_fingerprint, 16);
+ g_print ("\n");
+ break;
+ }
+ case LM_SSL_STATUS_GENERIC_ERROR:
+ g_print ("Generic SSL error!\n");
+ break;
+ }
+
+ return LM_SSL_RESPONSE_CONTINUE;
+}
+
static void
authentication_cb (LmConnection *connection, gboolean result, gpointer ud)
{
@@ -92,7 +139,8 @@
#endif
if (argc < 4) {
- g_print (USAGE);
+ g_print ("Usage: test-lm <server> <username> <password>\n"
+ " test-lm <server> <username> <password> <fingerprint>\n");
return 1;
}
@@ -124,12 +172,11 @@
connection = lm_connection_new (argv[1]);
- /*
- if (lm_connection_supports_ssl ()) {
- lm_connection_set_port (connection, 5223);
- lm_connection_set_use_ssl (connection, TRUE);
+ if (argc > 4 && !lm_connection_supports_ssl ()) {
+ g_error ("No SSL support!");
+ exit (1);
}
- */
+
handler = lm_message_handler_new (handle_messages, NULL, NULL);
lm_connection_register_message_handler (connection, handler,
@@ -142,9 +189,25 @@
info->name = g_strdup (argv[2]);
info->passwd = g_strdup (argv[3]);
- result = lm_connection_open (connection,
- (LmResultFunction) connection_open_cb,
- info, NULL, NULL);
+ if (argc > 4) {
+ int i;
+ char *p;
+ lm_connection_set_port (connection,
+ LM_CONNECTION_DEFAULT_PORT_SSL);
+
+ for (i = 0, p = argv[4]; *p && *(p+1); i++, p += 3)
+ expected_fingerprint[i] = (unsigned char) g_ascii_strtoull (p, NULL, 16);
+
+ result = lm_connection_open_ssl (connection,
+ expected_fingerprint,
+ (LmSSLFunction) ssl_cb,
+ (LmResultFunction) connection_open_cb,
+ info, NULL, NULL);
+ } else {
+ result = lm_connection_open (connection,
+ (LmResultFunction) connection_open_cb,
+ info, NULL, NULL);
+ }
if (!result) {
g_print ("Opening connection failed: %d\n", result);