aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/pop3
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/pop3')
-rw-r--r--camel/providers/pop3/Makefile.am4
-rw-r--r--camel/providers/pop3/camel-pop3-store.c133
2 files changed, 127 insertions, 10 deletions
diff --git a/camel/providers/pop3/Makefile.am b/camel/providers/pop3/Makefile.am
index 49bb2fc254..f30d73e736 100644
--- a/camel/providers/pop3/Makefile.am
+++ b/camel/providers/pop3/Makefile.am
@@ -17,7 +17,7 @@ INCLUDES = \
-I$(top_srcdir)/intl \
$(GTK_INCLUDEDIR) \
-I$(top_srcdir)/camel \
- -I$(srcdir)/../mbox \
+ $(KRB4_CFLAGS) \
-DG_LOG_DOMAIN=\"camel-pop3-provider\"
libcamelpop3_la_SOURCES = \
@@ -30,6 +30,6 @@ libcamelpop3include_HEADERS = \
camel-pop3-store.h
-libcamelpop3_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir)
+libcamelpop3_la_LDFLAGS = $(KRB4_LDFLAGS) -version-info 0:0:0 -rpath $(libdir)
EXTRA_DIST = libcamelpop3.urls
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 4f4410234d..eb5c77558e 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -46,13 +46,20 @@
/* Specified in RFC 1939 */
#define POP3_PORT 110
+#ifdef HAVE_KRB4
+/* Specified nowhere */
+#define KPOP_PORT 1109
+
+#include <krb.h>
+#endif
+
static CamelServiceClass *service_class = NULL;
static void finalize (GtkObject *object);
static gboolean pop3_connect (CamelService *service, CamelException *ex);
static gboolean pop3_disconnect (CamelService *service, CamelException *ex);
-static GList *query_auth_types (CamelService *service);
+static GList *query_auth_types (CamelService *service, CamelException *ex);
static void free_auth_types (CamelService *service, GList *authtypes);
static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
@@ -139,7 +146,7 @@ finalize (GtkObject *object)
static CamelServiceAuthType password_authtype = {
- "Password/APOP",
+ "Password",
"This option will connect to the POP server using the APOP "
"protocol if possible, or a plaintext password if not.",
@@ -148,12 +155,78 @@ static CamelServiceAuthType password_authtype = {
TRUE
};
-static GList
-*query_auth_types (CamelService *service)
+#ifdef HAVE_KRB4
+static CamelServiceAuthType kpop_authtype = {
+ "Kerberos 4 (KPOP)",
+
+ "This will connect to the POP server and use Kerberos 4 "
+ "to authenticate to it.",
+
+ "+KPOP",
+ FALSE
+};
+
+static gboolean
+try_connect (CamelService *service, CamelException *ex)
+{
+ struct hostent *h;
+ struct sockaddr_in sin;
+ int fd;
+
+ h = camel_service_gethost (service, ex);
+ if (!h)
+ return FALSE;
+
+ sin.sin_family = h->h_addrtype;
+ if (service->url->port)
+ sin.sin_port = htons (service->url->port);
+ else
+ sin.sin_port = htons (POP3_PORT);
+ memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
+
+ fd = socket (h->h_addrtype, SOCK_STREAM, 0);
+ if (fd == -1 ||
+ connect (fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ if (fd > -1)
+ close (fd);
+ return FALSE;
+ }
+
+ close (fd);
+ return TRUE;
+}
+#endif
+
+static GList *
+query_auth_types (CamelService *service, CamelException *ex)
{
- GList *ret;
+ GList *ret = NULL;
+ gboolean passwd = TRUE;
+#ifdef HAVE_KRB4
+ gboolean kpop = TRUE;
+ int saved_port;
+#endif
+
+ if (service->url) {
+ passwd = try_connect (service, ex);
+ if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
+ return NULL;
+#ifdef HAVE_KRB4
+ saved_port = service->url->port;
+ service->url->port = KPOP_PORT;
+ kpop = try_connect (service, ex);
+ service->url->port = saved_port;
+ if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
+ return NULL;
+#endif
+ }
- ret = g_list_append (NULL, &password_authtype);
+ if (passwd)
+ ret = g_list_append (ret, &password_authtype);
+#ifdef HAVE_KRB4
+ if (kpop)
+ ret = g_list_append (ret, &kpop_authtype);
+#endif
return ret;
}
@@ -213,12 +286,16 @@ pop3_connect (CamelService *service, CamelException *ex)
int fd, status;
char *buf, *apoptime, *apopend;
CamelPop3Store *store = CAMEL_POP3_STORE (service);
+#ifdef HAVE_KRB4
+ gboolean kpop = (service->url->authmech &&
+ !strcmp (service->url->authmech, "+KPOP"));
+#endif
h = camel_service_gethost (service, ex);
if (!h)
return FALSE;
- if (!service->url->passwd) {
+ if (!service->url->authmech && !service->url->passwd) {
char *prompt = g_strdup_printf ("Please enter the POP3 password for %s@%s",
service->url->user, h->h_name);
service->url->passwd =
@@ -232,7 +309,15 @@ pop3_connect (CamelService *service, CamelException *ex)
}
sin.sin_family = h->h_addrtype;
- sin.sin_port = htons (service->url->port ? service->url->port : POP3_PORT);
+ if (service->url->port)
+ sin.sin_port = service->url->port;
+#ifdef HAVE_KRB4
+ else if (kpop)
+ sin.sin_port = KPOP_PORT;
+#endif
+ else
+ sin.sin_port = POP3_PORT;
+ sin.sin_port = htons (sin.sin_port);
memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
fd = socket (h->h_addrtype, SOCK_STREAM, 0);
@@ -247,6 +332,38 @@ pop3_connect (CamelService *service, CamelException *ex)
return FALSE;
}
+#ifdef HAVE_KRB4
+ if (kpop) {
+ KTEXT_ST ticket_st;
+ MSG_DAT msg_data;
+ CREDENTIALS cred;
+ Key_schedule schedule;
+ char *hostname;
+
+ /* Need to copy hostname, because krb_realmofhost will
+ * call gethostbyname as well, and gethostbyname uses
+ * static storage.
+ */
+ hostname = g_strdup (h->h_name);
+ status = krb_sendauth (0, fd, &ticket_st, "pop", hostname,
+ krb_realmofhost (hostname), 0,
+ &msg_data, &cred, schedule,
+ NULL, NULL, "KPOPV0.1");
+ g_free (hostname);
+ if (status != KSUCCESS) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not authenticate to KPOP "
+ "server: %s",
+ krb_err_txt[status]);
+ close (fd);
+ return FALSE;
+ }
+
+ if (!service->url->passwd)
+ service->url->passwd = g_strdup (service->url->user);
+ }
+#endif /* HAVE_KRB4 */
+
store->ostream = camel_stream_fs_new_with_fd (fd);
store->istream = camel_stream_buffer_new (store->ostream,
CAMEL_STREAM_BUFFER_READ);