On Thu, 2019-05-09 at 11:03 -0700, James Bottomley wrote:
> I can certainly test things out.

        Hi,
that's great, thanks.

> To be honest, I've had problems with TLSv1.3 every time it's been
> negotiated, so disabling it is a reasonable thing to do.

I see. If you are still willing to help, then it'll be appreciated.

> I suppose there's no gntuls-cli equivalent for glib-networking?  That
> would be the best way to test it.

I agree, but I'm not aware of anything like that (which doesn't mean it
doesn't exist). I made a little test program as promised, see the
attachment. The first line contains a comment with a command to compile
and run it (against Google's IMAP server). It's only a test program,
mimic-ing what Evolution (or better Camel library from evolution-data-
server) does. You may have installed development packages for glib and,
if split, also for glib's gio, to be able to compile it.

        Bye,
        Milan

P.S.: The result of the run as is in the file itself is below:


$ ./imap-conn imap.googlemail.com 993

Connected to imap.googlemail.com:993
Response: * OK Gimap ready for requests from {IPADDRESS} {SOMETOKEN}

Request:  A01 CAPABILITY
Response: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST 
CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN 
AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
A01 OK Thats all she wrote! {SOMETOKEN}

Request:  A02 LOGOUT
Response: * BYE Logout Requested {SOMETOKEN}
A02 OK Quoth the raven, nevermore... {SOMETOKEN}

/* gcc `pkg-config --cflags --libs glib-2.0 gio-2.0` imap-conn.c -g -O0 -o imap-conn && ./imap-conn imap.googlemail.com 993 */

#include <glib.h>
#include <gio/gio.h>

static gboolean
read_stream_data (GIOStream *stream)
{
	GInputStream *input;
	gchar buffer[2048 + 1];
	gsize count;
	GError *error = NULL;

	input = g_io_stream_get_input_stream (stream);

	count = g_input_stream_read (input, buffer, G_N_ELEMENTS (buffer) - 1, NULL, &error);

	if (count == -1) {
		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
			g_clear_error (&error);
		} else {
			g_printerr ("Failed to read data from the server: %s\n", error ? error->message : "Unknown error");
			g_clear_error (&error);
			return FALSE;
		}
	} else {
		buffer[count] = 0;
		g_print ("Response: %s\n", buffer);
	}

	return TRUE;
}

static gboolean
issue_command (GIOStream *stream,
	       const gchar *command)
{
	GOutputStream *output;
	gsize count, written = 0;
	GError *error = NULL;

	output = g_io_stream_get_output_stream (stream);

	count = strlen (command);
	if (!g_output_stream_write_all (output, command, count, &written, NULL, &error)) {
		g_printerr ("Failed to write command to the output stream: %s\n", error ? error->message : "Unknown error");
		g_clear_error (&error);
		return FALSE;
	}

	if (written != count) {
		g_printerr ("Wrote only %d bytes, instead of %d\n", written, count);
		return FALSE;
	}

	if (!g_output_stream_write_all (output, "\r\n", 2, &written, NULL, &error)) {
		g_printerr ("Failed to write command end to the output stream: %s\n", error ? error->message : "Unknown error");
		g_clear_error (&error);
		return FALSE;
	}

	if (written != 2) {
		g_printerr ("Wrote only %d bytes, instead of %d\n", written, 2);
		return FALSE;
	}

	if (!g_output_stream_flush (output, NULL, &error)) {
		g_printerr ("Failed to flush output stream\n", error ? error->message : "Unknown error");
		g_clear_error (&error);
		return FALSE;
	}

	g_print ("Request:  %s\n", command);

	return read_stream_data (stream);
}

static gint
run_connection (const gchar *host,
		gushort port)
{
	GSocketConnectable *connectable;
	GSocketConnection *connection;
	GSocketClient *client;
	gint ret = 0;
	GError *error = NULL;

	connectable = g_object_new (G_TYPE_NETWORK_ADDRESS,
		"scheme", "imap",
		"hostname", host,
		"port", port,
		NULL);

	client = g_socket_client_new ();
	g_socket_client_set_timeout (client, 10);
	g_socket_client_set_tls (client, TRUE);

	connection = g_socket_client_connect (client, connectable, NULL, &error);

	if (connection) {
		GSocket *socket;
		GIOStream *stream;

		g_print ("Connected to %s:%d\n", host, port);

		socket = g_socket_connection_get_socket (connection);
		if (socket) {
			g_socket_set_timeout (socket, 10);
			g_socket_set_keepalive (socket, TRUE);
		}

		stream = G_IO_STREAM (connection);

		if (!read_stream_data (stream))
			ret = 3;
		else if (!issue_command (stream, "A01 CAPABILITY"))
			ret = 4;
		else if (!issue_command (stream, "A02 LOGOUT"))
			ret = 5;

		if (!g_io_stream_close (stream, NULL, &error)) {
			if (!ret)
				ret = 6;
			g_printerr ("Failed to close connection: %s\n", error ? error->message : "Unknown error");
			g_clear_error (&error);
		}

		g_object_unref (connection);
	} else {
		g_printerr ("Failed to connect to %s:%d: %s\n", host, port, error ? error->message : "Unknown error");
		g_clear_error (&error);
		ret = 2;
	}

	g_object_unref (connectable);
	g_object_unref (client);
}

gint
main (gint argc,
      gchar *argv[])
{
	const gchar *host;
	gushort port;

	if (argc != 3) {
		g_printerr ("Requires two arguments, IMAP server host name and port, in this order\n");
		return 1;
	}

	host = argv[1];
	port = (gushort) g_ascii_strtoll (argv[2], NULL, 10);

	return run_connection (host, port);
}
_______________________________________________
evolution-hackers mailing list
evolution-hackers@gnome.org
To change your list options or unsubscribe, visit ...
https://mail.gnome.org/mailman/listinfo/evolution-hackers

Reply via email to