Add PREAUTH handling and pine/mutt/etpan/etc.-style 'ssh <mailhost> exec

2003-09-04  David Woodhouse  <dwmw2@infradead.org>

	* providers/camel-imap-store.[ch]: Add PREAUTH handling and
	pine/mutt/etpan/etc.-style 'ssh <mailhost> exec imapd' support.

svn path=/trunk/; revision=22463
This commit is contained in:
David Woodhouse
2003-09-04 21:00:19 +00:00
committed by David Woodhouse
parent d1aa1d599d
commit 3cc69a3c19
3 changed files with 169 additions and 2 deletions

View File

@ -1,3 +1,8 @@
2003-09-04 David Woodhouse <dwmw2@infradead.org>
* providers/camel-imap-store.[ch]: Add PREAUTH handling and
pine/mutt/etpan/etc.-style 'ssh <mailhost> exec imapd' support.
2003-09-03 David Woodhouse <dwmw2@infradead.org>
* camel-stream-process.[ch]: New stream implementation for running

View File

@ -52,6 +52,7 @@
#include "camel-stream.h"
#include "camel-stream-buffer.h"
#include "camel-stream-fs.h"
#include "camel-stream-process.h"
#include "camel-tcp-stream-raw.h"
#include "camel-tcp-stream-ssl.h"
#include "camel-url.h"
@ -251,6 +252,7 @@ camel_imap_store_init (gpointer object, gpointer klass)
imap_store->dir_sep = '\0';
imap_store->current_folder = NULL;
imap_store->connected = FALSE;
imap_store->preauthed = FALSE;
imap_store->tag_prefix = imap_tag_prefix++;
if (imap_tag_prefix > 'Z')
@ -599,9 +601,10 @@ connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelE
store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
store->connected = TRUE;
store->preauthed = FALSE;
store->command = 0;
/* Read the greeting, if any. FIXME: deal with PREAUTH */
/* Read the greeting, if any, and deal with PREAUTH */
if (camel_imap_store_readline (store, &buf, ex) < 0) {
if (store->istream) {
camel_object_unref (CAMEL_OBJECT (store->istream));
@ -617,6 +620,8 @@ connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelE
return FALSE;
}
if (!strncmp(buf, "* PREAUTH", 9))
store->preauthed = TRUE;
g_free (buf);
/* get the imap server capabilities */
@ -728,6 +733,149 @@ connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelE
#endif /* HAVE_SSL */
}
static gboolean
connect_to_server_process (CamelService *service, const char *cmd, CamelException *ex)
{
CamelImapStore *store = (CamelImapStore *) service;
CamelStream *cmd_stream;
int ret, i = 0;
char *buf;
char *cmd_copy;
char *full_cmd;
char *child_env[7];
/* Put full details in the environment, in case the connection
program needs them */
buf = camel_url_to_string(service->url, 0);
child_env[i++] = g_strdup_printf("URL=%s", buf);
g_free(buf);
child_env[i++] = g_strdup_printf("URLHOST=%s", service->url->host);
if (service->url->port)
child_env[i++] = g_strdup_printf("URLPORT=%d", service->url->port);
if (service->url->user)
child_env[i++] = g_strdup_printf("URLUSER=%s", service->url->user);
if (service->url->passwd)
child_env[i++] = g_strdup_printf("URLPASSWD=%s", service->url->passwd);
if (service->url->path)
child_env[i++] = g_strdup_printf("URLPATH=%s", service->url->path);
child_env[i] = NULL;
/* Now do %h, %u, etc. substitution in cmd */
buf = cmd_copy = g_strdup(cmd);
full_cmd = "";
for(;;) {
char *pc;
char *tmp;
char *var;
int len;
pc = strchr(buf, '%');
ignore:
if (!pc) {
tmp = g_strdup_printf("%s%s", full_cmd, buf);
g_free(full_cmd);
full_cmd = tmp;
break;
}
len = pc - buf;
var = NULL;
switch(pc[1]) {
case 'h':
var = service->url->host;
break;
case 'u':
var = service->url->user;
break;
}
if (!var) {
/* If there wasn't a valid %-code, with an actual
variable to insert, pretend we didn't see the % */
pc = strchr(pc + 1, '%');
goto ignore;
}
tmp = g_strdup_printf("%s%.*s%s", full_cmd, len, buf, var);
g_free(full_cmd);
full_cmd = tmp;
buf = pc + 2;
}
g_free(cmd_copy);
cmd_stream = camel_stream_process_new ();
ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream),
full_cmd, (const char **)child_env);
while (i)
g_free(child_env[--i]);
if (ret == -1) {
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("Connection cancelled"));
else
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Could not connect with command \"%s\": %s"),
full_cmd, g_strerror (errno));
camel_object_unref (CAMEL_OBJECT (cmd_stream));
g_free(full_cmd);
return FALSE;
}
g_free(full_cmd);
store->ostream = cmd_stream;
store->istream = camel_stream_buffer_new (cmd_stream, CAMEL_STREAM_BUFFER_READ);
store->connected = TRUE;
store->preauthed = FALSE;
store->command = 0;
/* Read the greeting, if any, and deal with PREAUTH */
if (camel_imap_store_readline (store, &buf, ex) < 0) {
if (store->istream) {
camel_object_unref (CAMEL_OBJECT (store->istream));
store->istream = NULL;
}
if (store->ostream) {
camel_object_unref (CAMEL_OBJECT (store->ostream));
store->ostream = NULL;
}
store->connected = FALSE;
return FALSE;
}
if (!strncmp(buf, "* PREAUTH", 9))
store->preauthed = TRUE;
g_free (buf);
/* get the imap server capabilities */
if (!imap_get_capability (service, ex)) {
if (store->istream) {
camel_object_unref (CAMEL_OBJECT (store->istream));
store->istream = NULL;
}
if (store->ostream) {
camel_object_unref (CAMEL_OBJECT (store->ostream));
store->ostream = NULL;
}
store->connected = FALSE;
return FALSE;
}
return TRUE;
}
static struct {
char *value;
int mode;
@ -742,10 +890,16 @@ static struct {
static gboolean
connect_to_server_wrapper (CamelService *service, CamelException *ex)
{
const char *command;
#ifdef HAVE_SSL
const char *use_ssl;
int i, ssl_mode;
#endif
command = camel_url_get_param (service->url, "command");
if (command)
return connect_to_server_process (service, command, ex);
#ifdef HAVE_SSL
use_ssl = camel_url_get_param (service->url, "use_ssl");
if (use_ssl) {
for (i = 0; ssl_options[i].value; i++)
@ -1070,6 +1224,13 @@ imap_auth_loop (CamelService *service, CamelException *ex)
CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
if (store->preauthed) {
if (camel_verbose_debug)
fprintf(stderr, "Server %s has preauthenticated us.\n",
service->url->host);
return TRUE;
}
if (service->url->authmech) {
if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,

View File

@ -107,6 +107,7 @@ struct _CamelImapStore {
/* Information about the command channel / connection status */
gboolean connected;
gboolean preauthed;
char tag_prefix;
guint32 command;
CamelFolder *current_folder;