[evolution-mapi] Bug #592779 - Authenticate using Kerberos
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #592779 - Authenticate using Kerberos
- Date: Wed, 10 Aug 2011 15:19:31 +0000 (UTC)
commit 6e731ab4ab1da39837ef42e0e32630e587cd370f
Author: Sean Finney <seanius seanius net>
Date: Wed Aug 10 17:18:48 2011 +0200
Bug #592779 - Authenticate using Kerberos
.../exchange-mapi-account-listener.c | 71 ++++++--
.../exchange-mapi-account-setup.c | 180 ++++++++++++++++---
src/addressbook/e-book-backend-mapi.c | 146 ++++++++++-------
src/calendar/Makefile.am | 6 +-
src/calendar/e-cal-backend-mapi.c | 111 ++++++++-----
src/camel/camel-mapi-store.c | 85 ++++++----
src/libexchangemapi/exchange-mapi-connection.c | 65 ++++---
src/libexchangemapi/exchange-mapi-connection.h | 25 ++-
src/libexchangemapi/exchange-mapi-utils.c | 101 ++++++++++-
src/libexchangemapi/exchange-mapi-utils.h | 5 +-
10 files changed, 567 insertions(+), 228 deletions(-)
---
diff --git a/src/account-setup-eplugin/exchange-mapi-account-listener.c b/src/account-setup-eplugin/exchange-mapi-account-listener.c
index 1369a58..d5a9174 100644
--- a/src/account-setup-eplugin/exchange-mapi-account-listener.c
+++ b/src/account-setup-eplugin/exchange-mapi-account-listener.c
@@ -45,6 +45,17 @@
#define d(x)
+#define SET_KRB_SSO(_esource, _krbval) \
+ G_STMT_START { \
+ ESource *tmp_src = (_esource); \
+ const gchar *tmp_val = (_krbval); \
+ e_source_set_property (tmp_src, "kerberos", tmp_val); \
+ if (tmp_val && g_str_equal (tmp_val, "required")) { \
+ e_source_set_property (tmp_src, "auth", NULL); \
+ e_source_set_property (tmp_src, "auth-type", NULL); \
+ } \
+ } G_STMT_END
+
G_DEFINE_TYPE (ExchangeMAPIAccountListener, exchange_mapi_account_listener, G_TYPE_OBJECT)
static gboolean create_profile_entry (CamelURL *url, EAccount *account);
@@ -219,7 +230,7 @@ add_cal_esource (EAccount *account, GSList *folders, ExchangeMAPIFolderType fold
{
ESourceList *source_list = NULL;
ESourceGroup *group = NULL;
- const gchar *conf_key = NULL, *source_selection_key = NULL;
+ const gchar *conf_key = NULL, *source_selection_key = NULL, *kerberos;
GConfClient* client;
GSList *ids, *temp_list, *old_sources = NULL;
gchar *base_uri = NULL;
@@ -262,6 +273,9 @@ add_cal_esource (EAccount *account, GSList *folders, ExchangeMAPIFolderType fold
e_source_group_set_property (group, "host", url->host);
e_source_group_set_property (group, "profile", camel_url_get_param (url, "profile"));
e_source_group_set_property (group, "domain", camel_url_get_param (url, "domain"));
+ e_source_group_set_property (group, "realm", camel_url_get_param (url, "realm"));
+ kerberos = camel_url_get_param (url, "kerberos");
+ e_source_group_set_property (group, "kerberos", kerberos);
/* We set these because on new folder creation - these are required. */
e_source_group_set_property (group, "acl-user-name", account->id->name);
@@ -297,8 +311,10 @@ add_cal_esource (EAccount *account, GSList *folders, ExchangeMAPIFolderType fold
e_source_set_property (source, "host", url->host);
e_source_set_property (source, "profile", camel_url_get_param (url, "profile"));
e_source_set_property (source, "domain", camel_url_get_param (url, "domain"));
+ e_source_set_property (source, "realm", camel_url_get_param (url, "realm"));
e_source_set_property (source, "folder-id", fid);
e_source_set_property (source, "public", "no");
+ SET_KRB_SSO(source, kerberos);
if (is_new_source)
e_source_set_property (source, "offline_sync",
@@ -369,7 +385,7 @@ void exchange_mapi_add_esource (CamelURL *url, const gchar *folder_name, const g
{
ESourceList *source_list = NULL;
ESourceGroup *group = NULL;
- const gchar *conf_key = NULL;
+ const gchar *conf_key = NULL, *kerberos = NULL;
GConfClient* client;
GSList *sources;
ESource *source = NULL;
@@ -413,6 +429,7 @@ void exchange_mapi_add_esource (CamelURL *url, const gchar *folder_name, const g
}
relative_uri = g_strconcat (";", fid, NULL);
+ kerberos = camel_url_get_param (url, "kerberos");
source = e_source_new (folder_name, relative_uri);
e_source_set_property (source, "auth", "1");
e_source_set_property (source, "auth-type", "plain/password");
@@ -420,11 +437,13 @@ void exchange_mapi_add_esource (CamelURL *url, const gchar *folder_name, const g
e_source_set_property (source, "host", url->host);
e_source_set_property (source, "profile", camel_url_get_param (url, "profile"));
e_source_set_property (source, "domain", camel_url_get_param (url, "domain"));
+ e_source_set_property (source, "realm", camel_url_get_param (url, "realm"));
e_source_set_property (source, "folder-id", fid);
e_source_set_property (source, "offline_sync",
camel_url_get_param (url, "offline_sync") ? "1" : "0");
e_source_set_property (source, "public", "yes");
e_source_set_property (source, "delete", "yes");
+ SET_KRB_SSO(source, kerberos);
e_source_group_add_source (group, source, -1);
@@ -624,6 +643,7 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
GSList *temp_list, *old_sources = NULL;
GConfClient* client;
gboolean is_new_group = FALSE;
+ const gchar *kerberos = NULL;
url = camel_url_new (account->source->url, NULL);
if (url == NULL) {
@@ -647,11 +667,14 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
is_new_group = TRUE;
old_sources = NULL;
}
+ kerberos = camel_url_get_param (url, "kerberos");
e_source_group_set_property (group, "user", NULL);
e_source_group_set_property (group, "username", url->user);
e_source_group_set_property (group, "host", url->host);
e_source_group_set_property (group, "profile", camel_url_get_param (url, "profile"));
e_source_group_set_property (group, "domain", camel_url_get_param (url, "domain"));
+ e_source_group_set_property (group, "realm", camel_url_get_param (url, "realm"));
+ e_source_group_set_property (group, "kerberos", kerberos);
for (temp_list = folders; temp_list != NULL; temp_list = g_slist_next (temp_list)) {
ExchangeMAPIFolder *folder = temp_list->data;
@@ -680,8 +703,10 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
e_source_set_property(source, "host", url->host);
e_source_set_property(source, "profile", camel_url_get_param (url, "profile"));
e_source_set_property(source, "domain", camel_url_get_param (url, "domain"));
+ e_source_set_property(source, "realm", camel_url_get_param (url, "realm"));
e_source_set_property(source, "folder-id", fid);
e_source_set_property (source, "public", "no");
+ SET_KRB_SSO(source, kerberos);
if (is_new_source) {
e_source_set_property (source, "offline_sync",
@@ -744,6 +769,8 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
e_source_set_property(source, "view-limit", camel_url_get_param (url, "ad_limit"));
e_source_set_property(source, "profile", camel_url_get_param (url, "profile"));
e_source_set_property(source, "domain", camel_url_get_param (url, "domain"));
+ e_source_set_property(source, "realm", camel_url_get_param (url, "realm"));
+ SET_KRB_SSO(source, kerberos);
if (is_new_source) {
e_source_set_property(source, "offline_sync", "1");
@@ -1101,42 +1128,45 @@ create_profile_entry (CamelURL *url, EAccount *account)
{
gboolean status = FALSE;
guint8 attempts = 0;
+ ExchangeMapiProfileData empd = { 0 };
if (!e_shell_get_online (e_shell_get_default ()))
return FALSE;
+ exchange_mapi_util_profiledata_from_camelurl (&empd, url);
+
while (!status && attempts <= 3) {
- gchar *password = NULL, *key = NULL;
+ gchar *key = NULL;
key = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD | CAMEL_URL_HIDE_PARAMS);
- if (!attempts)
- password = e_passwords_get_password (NULL, key);
- if (!password) {
+ if (!attempts && !empd.krb_sso)
+ empd.password = e_passwords_get_password (NULL, key);
+ if (!empd.password && !empd.krb_sso) {
gboolean remember = account && e_account_get_bool (account, E_ACCOUNT_SOURCE_SAVE_PASSWD);
gchar *title;
- title = g_strdup_printf (_("Enter Password for %s %s"), url->user, url->host);
- password = e_passwords_ask_password (title, NULL, key, title,
- E_PASSWORDS_REMEMBER_FOREVER | E_PASSWORDS_SECRET | (attempts ? E_PASSWORDS_REPROMPT : 0),
- &remember, NULL);
+ title = g_strdup_printf (_("Enter Password for %s %s"),
+ url->user, url->host);
+ empd.password = e_passwords_ask_password (title, NULL, key, title, E_PASSWORDS_REMEMBER_FOREVER | E_PASSWORDS_SECRET | (attempts ? E_PASSWORDS_REPROMPT : 0), &remember, NULL);
g_free (title);
}
g_free (key);
- if (password) {
+
+ if (empd.password || empd.krb_sso) {
GError *error = NULL;
- guint32 cp_flags = (camel_url_get_param (url, "ssl") && g_str_equal (camel_url_get_param (url, "ssl"), "1")) ? CREATE_PROFILE_FLAG_USE_SSL : CREATE_PROFILE_FLAG_NONE;
- status = exchange_mapi_create_profile (url->user, password, camel_url_get_param (url, "domain"), url->host, cp_flags, NULL, NULL, &error);
+ status = exchange_mapi_create_profile (&empd, NULL,
+ NULL, &error);
if (status) {
/* profile was created, try to connect to the server */
ExchangeMapiConnection *conn;
gchar *profname;
status = FALSE;
- profname = exchange_mapi_util_profile_name (url->user, camel_url_get_param (url, "domain"), url->host, FALSE);
+ profname = exchange_mapi_util_profile_name (&empd, FALSE);
- conn = exchange_mapi_connection_new (profname, password, &error);
+ conn = exchange_mapi_connection_new (profname, empd.password, &error);
if (conn) {
status = exchange_mapi_connection_connected (conn);
g_object_unref (conn);
@@ -1169,7 +1199,7 @@ check_equal (const gchar *a, const gchar *b)
static gboolean
mapi_camel_url_equal (CamelURL *a, CamelURL *b)
{
- const gchar *params[] = { "profile", "domain", "ad_limit", "ad_server" };
+ const gchar *params[] = { "profile", "domain", "realm", "kerberos", "ad_limit", "ad_server" };
guint n_params = G_N_ELEMENTS (params), i;
gboolean retval = TRUE;
@@ -1191,6 +1221,7 @@ mapi_account_changed_async (gpointer worker_data, gboolean cancelled, gpointer u
ExchangeMAPIAccountInfo *existing_account_info = NULL;
EAccountList *account_listener = worker_data;
EAccount *account = user_data;
+ ExchangeMapiProfileData empd = { 0 };
g_return_if_fail (account_listener != NULL);
g_return_if_fail (account != NULL);
@@ -1212,7 +1243,10 @@ mapi_account_changed_async (gpointer worker_data, gboolean cancelled, gpointer u
gchar *profname = NULL, *uri = NULL;
ExchangeMAPIAccountListener *config_listener = exchange_mapi_accounts_peek_config_listener();
- profname = exchange_mapi_util_profile_name (new_url->user, camel_url_get_param (new_url, "domain"), new_url->host, FALSE);
+ exchange_mapi_util_profiledata_from_camelurl (&empd,
+ new_url);
+ profname = exchange_mapi_util_profile_name (&empd,
+ FALSE);
camel_url_set_param(new_url, "profile", profname);
g_free (profname);
@@ -1245,7 +1279,8 @@ mapi_account_changed_async (gpointer worker_data, gboolean cancelled, gpointer u
gchar *profname = NULL, *uri = NULL;
ExchangeMAPIAccountListener *config_listener = exchange_mapi_accounts_peek_config_listener();
- profname = exchange_mapi_util_profile_name (new_url->user, camel_url_get_param (new_url, "domain"), new_url->host, FALSE);
+ exchange_mapi_util_profiledata_from_camelurl (&empd, new_url);
+ profname = exchange_mapi_util_profile_name (&empd, FALSE);
camel_url_set_param(new_url, "profile", profname);
g_free (profname);
diff --git a/src/account-setup-eplugin/exchange-mapi-account-setup.c b/src/account-setup-eplugin/exchange-mapi-account-setup.c
index 5d1e030..04f540d 100644
--- a/src/account-setup-eplugin/exchange-mapi-account-setup.c
+++ b/src/account-setup-eplugin/exchange-mapi-account-setup.c
@@ -108,7 +108,7 @@ tree_selection_changed (GtkTreeSelection *selection, GtkDialog *dialog)
/* Callback for ProcessNetworkProfile. If we have more than one username,
we need to let the user select. */
static uint32_t
-create_profile_callback (struct SRowSet *rowset, gpointer data)
+create_profile_callback (struct SRowSet *rowset, gconstpointer data)
{
struct SPropValue *lpProp_fullname, *lpProp_account;
gint response;
@@ -208,13 +208,32 @@ create_profile_callback (struct SRowSet *rowset, gpointer data)
return index;
}
+static char*
+prompt_password(const gchar *user, const gchar *host, const gchar *key,
+ EMConfigTargetAccount *account)
+{
+ int pw_flags = E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET;
+ gchar *password, *title;
+ gboolean save;
+
+ password = e_passwords_get_password (NULL, key);
+ save = e_account_get_bool (account->modified_account,
+ E_ACCOUNT_SOURCE_SAVE_PASSWD);
+ title = g_strdup_printf (_("Enter Password for %s %s"), user, host);
+ password = e_passwords_ask_password (title, NULL, key, title, pw_flags,
+ &save, NULL);
+ g_free (title);
+ return password;
+}
+
static void
validate_credentials (GtkWidget *widget, EConfig *config)
{
EMConfigTargetAccount *target_account = (EMConfigTargetAccount *)(config->target);
CamelURL *url = NULL;
- gchar *key = NULL, *password = NULL;
- const gchar *domain_name = NULL;
+ gchar *key = NULL;
+ ExchangeMapiProfileData empd = { 0 };
+ GError *error = NULL;
if (!e_shell_get_online (e_shell_get_default ())) {
e_notice (NULL, GTK_MESSAGE_ERROR, "%s", _("Cannot create MAPI folders in offline mode."));
@@ -222,7 +241,6 @@ validate_credentials (GtkWidget *widget, EConfig *config)
}
url = camel_url_new (e_account_get_string (target_account->modified_account, E_ACCOUNT_SOURCE_URL), NULL);
- domain_name = camel_url_get_param (url, "domain");
/* Silently remove domain part from a username when user enters it as such.
This change will be visible in the UI on new edit open. */
@@ -235,32 +253,32 @@ validate_credentials (GtkWidget *widget, EConfig *config)
g_free (tmp);
}
- if (!url->user || !*url->user || !url->host || !*url->host || !domain_name || !*domain_name) {
+ exchange_mapi_util_profiledata_from_camelurl (&empd, url);
+ if (!empd.username || !*(empd.username)
+ || !empd.server || !*(empd.server)
+ || ((!empd.domain || !*(empd.domain))
+ && !empd.krb_sso)) {
e_notice (NULL, GTK_MESSAGE_ERROR, "%s", _("Server, username and domain name cannot be empty. Please fill them with correct values."));
camel_url_free (url);
return;
+ } else if (empd.krb_sso && (!empd.krb_realm || !*(empd.krb_realm))) {
+ e_notice (NULL, GTK_MESSAGE_ERROR, "%s", _("Realm name cannot be empty when kerberos is selected. Please fill them with correct values."));
+ camel_url_free (url);
+ return;
}
key = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD | CAMEL_URL_HIDE_PARAMS);
- password = e_passwords_get_password (NULL, key);
- if (!password || !*password) {
- gboolean remember = e_account_get_bool (target_account->modified_account, E_ACCOUNT_SOURCE_SAVE_PASSWD);
- gchar *title;
-
- g_free (password);
- title = g_strdup_printf (_("Enter Password for %s %s"), url->user, url->host);
- password = e_passwords_ask_password (title, NULL, key, title,
- E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET,
- &remember, NULL);
- g_free (title);
+ if (empd.krb_sso) {
+ exchange_mapi_util_trigger_krb_auth (&empd, &error);
+ } else {
+ empd.password = prompt_password(empd.username, empd.server,
+ key, target_account);
}
- /*Can there be a account without password ?*/
- if (password && *password && domain_name && *domain_name && *url->user && *url->host) {
- guint32 cp_flags = (camel_url_get_param (url, "ssl") && g_str_equal (camel_url_get_param (url, "ssl"), "1")) ? CREATE_PROFILE_FLAG_USE_SSL : CREATE_PROFILE_FLAG_NONE;
- GError *error = NULL;
- gboolean status = exchange_mapi_create_profile (url->user, password, domain_name, url->host, cp_flags,
- (mapi_profile_callback_t) create_profile_callback, url->user,
+ if (COMPLETE_PROFILEDATA(&empd)) {
+ gboolean status = exchange_mapi_create_profile (&empd,
+ (mapi_profile_callback_t) create_profile_callback,
+ empd.username,
&error);
if (status) {
/* profile was created, try to connect to the server */
@@ -268,9 +286,10 @@ validate_credentials (GtkWidget *widget, EConfig *config)
gchar *profname;
status = FALSE;
- profname = exchange_mapi_util_profile_name (url->user, domain_name, url->host, FALSE);
+ profname = exchange_mapi_util_profile_name (&empd,
+ FALSE);
- conn = exchange_mapi_connection_new (profname, password, &error);
+ conn = exchange_mapi_connection_new (profname, empd.password, &error);
if (conn) {
status = exchange_mapi_connection_connected (conn);
g_object_unref (conn);
@@ -283,7 +302,8 @@ validate_credentials (GtkWidget *widget, EConfig *config)
/* Things are successful */
gchar *profname = NULL, *uri = NULL;
- profname = exchange_mapi_util_profile_name (url->user, domain_name, url->host, FALSE);
+ profname = exchange_mapi_util_profile_name (&empd,
+ FALSE);
camel_url_set_param (url, "profile", profname);
g_free (profname);
@@ -305,14 +325,15 @@ validate_credentials (GtkWidget *widget, EConfig *config)
g_free (e);
}
- if (error)
- g_error_free (error);
} else {
e_passwords_forget_password (NULL, key);
e_notice (NULL, GTK_MESSAGE_ERROR, "%s", _("Authentication failed."));
}
- g_free (password);
+ if (error)
+ g_error_free (error);
+
+ g_free (empd.password);
g_free (key);
camel_url_free (url);
}
@@ -342,6 +363,49 @@ domain_entry_changed(GtkWidget *entry, EConfig *config)
}
static void
+realm_entry_changed (GtkWidget *entry, EConfig *config)
+{
+ EMConfigTargetAccount *target = (EMConfigTargetAccount *)(config->target);
+ CamelURL *url = NULL;
+ const gchar *realm = NULL;
+ gchar *url_string = NULL;
+
+ url = camel_url_new (e_account_get_string(target->modified_account, E_ACCOUNT_SOURCE_URL), NULL);
+ realm = gtk_entry_get_text (GTK_ENTRY(entry));
+
+ if (realm && realm[0])
+ camel_url_set_param (url, "realm", realm);
+ else
+ camel_url_set_param (url, "realm", NULL);
+
+ url_string = camel_url_to_string (url, 0);
+ e_account_set_string (target->modified_account, E_ACCOUNT_SOURCE_URL, url_string);
+ e_account_set_string (target->modified_account, E_ACCOUNT_TRANSPORT_URL, url_string);
+ g_free (url_string);
+
+ camel_url_free (url);
+}
+
+static void
+krb_sso_check_toggled (GtkWidget *check, EConfig *config)
+{
+ EMConfigTargetAccount *target = (EMConfigTargetAccount *)(config->target);
+ CamelURL *url = NULL;
+ gchar *url_string = NULL;
+
+ url = camel_url_new (e_account_get_string (target->modified_account, E_ACCOUNT_SOURCE_URL), NULL);
+
+ camel_url_set_param (url, "kerberos", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)) ? "required" : NULL);
+
+ url_string = camel_url_to_string (url, 0);
+ e_account_set_string (target->modified_account, E_ACCOUNT_SOURCE_URL, url_string);
+ e_account_set_string (target->modified_account, E_ACCOUNT_TRANSPORT_URL, url_string);
+ g_free (url_string);
+
+ camel_url_free (url);
+}
+
+static void
secure_check_toggled (GtkWidget *check, EConfig *config)
{
EMConfigTargetAccount *target = (EMConfigTargetAccount *)(config->target);
@@ -360,6 +424,15 @@ secure_check_toggled (GtkWidget *check, EConfig *config)
camel_url_free (url);
}
+static void
+widget_sanitizer_cb (GtkToggleButton *button, GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+ g_return_if_fail (GTK_IS_WIDGET (button));
+
+ gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (button));
+}
+
GtkWidget *
org_gnome_exchange_mapi_account_setup (EPlugin *epl, EConfigHookItemFactoryData *data)
{
@@ -378,10 +451,14 @@ org_gnome_exchange_mapi_account_setup (EPlugin *epl, EConfigHookItemFactoryData
if (!g_ascii_strcasecmp (url->protocol, "mapi")) {
GtkWidget *label;
GtkWidget *domain_name;
+ GtkWidget *realm_name;
GtkWidget *auth_button;
GtkWidget *secure_conn;
+ GtkWidget *krb_sso;
const gchar *domain_value = camel_url_get_param (url, "domain");
+ const gchar *realm_value = camel_url_get_param (url, "realm");
const gchar *use_ssl = camel_url_get_param (url, "ssl");
+ const gchar *kerberos = camel_url_get_param (url, "kerberos");
g_object_get (data->parent, "n-rows", &row, NULL);
@@ -406,12 +483,37 @@ org_gnome_exchange_mapi_account_setup (EPlugin *epl, EConfigHookItemFactoryData
gtk_table_attach (GTK_TABLE (data->parent), GTK_WIDGET (hgrid), 1, 2, row, row+1, GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
row++;
-
secure_conn = gtk_check_button_new_with_mnemonic (_("_Use secure connection"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (secure_conn), use_ssl && g_str_equal (use_ssl, "1"));
g_signal_connect (secure_conn, "toggled", G_CALLBACK (secure_check_toggled), data->config);
gtk_widget_show (secure_conn);
gtk_table_attach (GTK_TABLE (data->parent), GTK_WIDGET (secure_conn), 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+ row++;
+ krb_sso = gtk_check_button_new_with_mnemonic (_("_Kerberos authentication"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (krb_sso), kerberos && g_str_equal (kerberos, "required"));
+ g_signal_connect (krb_sso, "toggled", G_CALLBACK (krb_sso_check_toggled), data->config);
+ gtk_widget_show (krb_sso);
+ gtk_table_attach (GTK_TABLE (data->parent), GTK_WIDGET (krb_sso), 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+ row++;
+ label = gtk_label_new_with_mnemonic (_("_Realm name:"));
+ gtk_widget_show (label);
+
+ realm_name = gtk_entry_new ();
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), realm_name);
+ if (realm_value && *realm_value)
+ gtk_entry_set_text (GTK_ENTRY (realm_name), realm_value);
+ gtk_widget_show (realm_name);
+ g_signal_connect (realm_name, "changed", G_CALLBACK(realm_entry_changed), data->config);
+ gtk_table_attach (GTK_TABLE (data->parent), label, 0, 1, row, row + 1, 0, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (data->parent), GTK_WIDGET (realm_name), 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+ g_signal_connect (krb_sso, "toggled", G_CALLBACK (widget_sanitizer_cb), label);
+ g_signal_connect (krb_sso, "toggled", G_CALLBACK (widget_sanitizer_cb), realm_name);
+
+ widget_sanitizer_cb (GTK_TOGGLE_BUTTON (krb_sso), label);
+ widget_sanitizer_cb (GTK_TOGGLE_BUTTON (krb_sso), realm_name);
}
camel_url_free (url);
@@ -774,6 +876,7 @@ exchange_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
EABConfigTargetSource *t = (EABConfigTargetSource *) target;
ESource *source = t->source;
gchar *uri_text, *r_uri, *sfid;
+ const gchar *kerberos = NULL;
ESourceGroup *grp;
ExchangeMapiConnection *conn;
mapi_id_t fid, pfid;
@@ -815,6 +918,13 @@ exchange_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
e_source_set_property(source, "host", e_source_group_get_property (grp, "host"));
e_source_set_property(source, "profile", e_source_group_get_property (grp, "profile"));
e_source_set_property(source, "domain", e_source_group_get_property (grp, "domain"));
+ e_source_set_property(source, "realm", e_source_group_get_property (grp, "realm"));
+ kerberos = e_source_group_get_property (grp, "kerberos");
+ e_source_set_property(source, "kerberos", kerberos);
+ if (kerberos && g_str_equal (kerberos, "required")) {
+ e_source_set_property (source, "auth", NULL);
+ e_source_set_property (source, "auth-type", NULL);
+ }
e_source_set_relative_uri (source, g_strconcat (";",e_source_peek_name (source), NULL));
e_source_set_property (source, "completion", "true");
@@ -940,6 +1050,18 @@ exchange_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
e_source_set_property (source, "domain", tmp);
g_free (tmp);
+ tmp = e_source_group_get_property (group, "realm");
+ e_source_set_property (source, "realm", tmp);
+ g_free (tmp);
+
+ tmp = e_source_group_get_property (group, "kerberos");
+ e_source_set_property (source, "kerberos", tmp);
+ if (tmp && g_str_equal (tmp, "required")) {
+ e_source_set_property (source, "auth", NULL);
+ e_source_set_property (source, "auth-type", NULL);
+ }
+ g_free (tmp);
+
tmp = exchange_mapi_util_mapi_id_to_string (fid);
e_source_set_property (source, "folder-id", tmp);
g_free (tmp);
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index 4493f07..9b0c1a5 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -385,12 +385,70 @@ ebbm_update_cache_cb (gpointer data)
}
static void
+ebbm_connect_user (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *password, GError **error)
+{
+ EBookBackendMAPIPrivate *priv = ebma->priv;
+ GError *mapi_error = NULL;
+ ExchangeMapiConnection *old_conn;
+
+ if (!e_book_backend_is_online (E_BOOK_BACKEND (ebma))) {
+ ebbm_notify_connection_status (ebma, FALSE);
+ } else {
+ if (priv->update_cache_thread) {
+ g_cancellable_cancel (priv->update_cache);
+ g_thread_join (priv->update_cache_thread);
+ priv->update_cache_thread = NULL;
+ }
+
+ e_book_backend_mapi_lock_connection (ebma);
+
+ old_conn = priv->conn;
+ priv->conn = NULL;
+
+ priv->conn = exchange_mapi_connection_new (priv->profile,
+ password,
+ &mapi_error);
+ if (!priv->conn) {
+ priv->conn = exchange_mapi_connection_find (priv->profile);
+ if (priv->conn && !exchange_mapi_connection_connected (priv->conn))
+ exchange_mapi_connection_reconnect (priv->conn, password, &mapi_error);
+ }
+
+ if (old_conn)
+ g_object_unref (old_conn);
+
+ if (!priv->conn || mapi_error) {
+ if (priv->conn) {
+ g_object_unref (priv->conn);
+ priv->conn = NULL;
+ }
+
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Cannot connect"));
+ e_book_backend_mapi_unlock_connection (ebma);
+
+ if (mapi_error)
+ g_error_free (mapi_error);
+
+ ebbm_notify_connection_status (ebma, FALSE);
+ return;
+ }
+
+ e_book_backend_mapi_unlock_connection (ebma);
+
+ ebbm_notify_connection_status (ebma, TRUE);
+
+ /* if (priv->marked_for_offline) */
+ priv->update_cache_thread = g_thread_create (ebbm_update_cache_cb, ebma, TRUE, NULL);
+ }
+}
+
+static void
ebbm_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
EBookBackendMAPIPrivate *priv = ebma->priv;
ESource *source = e_book_backend_get_source (E_BOOK_BACKEND (ebma));
const gchar *offline;
- const gchar *cache_dir;
+ const gchar *cache_dir, *krb_sso;
GError *error = NULL;
if (e_book_backend_is_opened (E_BOOK_BACKEND (ebma))) {
@@ -443,7 +501,14 @@ ebbm_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean only_if_e
}
e_book_backend_notify_online (E_BOOK_BACKEND (ebma), TRUE);
- e_book_backend_notify_auth_required (E_BOOK_BACKEND (ebma), TRUE, NULL);
+ krb_sso = e_source_get_property (source, "kerberos");
+ if (!krb_sso || !g_str_equal (krb_sso, "required")) {
+ e_book_backend_notify_auth_required (E_BOOK_BACKEND (ebma),
+ TRUE, NULL);
+ } else {
+ ebbm_connect_user (ebma, cancellable, NULL, perror);
+ e_book_backend_notify_opened (E_BOOK_BACKEND (ebma), NULL);
+ }
}
static void
@@ -520,66 +585,13 @@ ebbm_get_backend_property (EBookBackendMAPI *ebma, const gchar *prop_name, gchar
static void
ebbm_authenticate_user (EBookBackendMAPI *ebma, GCancellable *cancellable, ECredentials *credentials, GError **error)
{
- EBookBackendMAPIPrivate *priv = ebma->priv;
- GError *mapi_error = NULL;
- ExchangeMapiConnection *old_conn;
+ const gchar *password;
if (!e_book_backend_is_online (E_BOOK_BACKEND (ebma))) {
ebbm_notify_connection_status (ebma, FALSE);
} else {
- if (priv->update_cache_thread) {
- g_cancellable_cancel (priv->update_cache);
- g_thread_join (priv->update_cache_thread);
- priv->update_cache_thread = NULL;
- }
-
- e_book_backend_mapi_lock_connection (ebma);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
- e_book_backend_mapi_unlock_connection (ebma);
- return;
- }
-
- old_conn = priv->conn;
- priv->conn = NULL;
-
- priv->conn = exchange_mapi_connection_new (priv->profile, e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), &mapi_error);
- if (!priv->conn) {
- priv->conn = exchange_mapi_connection_find (priv->profile);
- if (priv->conn && !exchange_mapi_connection_connected (priv->conn))
- exchange_mapi_connection_reconnect (priv->conn, e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), &mapi_error);
- }
-
- if (old_conn)
- g_object_unref (old_conn);
-
- if (!priv->conn || mapi_error) {
- if (priv->conn) {
- g_object_unref (priv->conn);
- priv->conn = NULL;
- }
-
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Cannot connect"));
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (mapi_error)
- g_error_free (mapi_error);
-
- ebbm_notify_connection_status (ebma, FALSE);
- return;
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-
- ebbm_notify_connection_status (ebma, TRUE);
-
- if (!g_cancellable_is_cancelled (cancellable) /* && priv->marked_for_offline */) {
- g_object_ref (ebma);
-
- priv->update_cache_thread = g_thread_create (ebbm_update_cache_cb, ebma, TRUE, NULL);
- if (!priv->update_cache_thread)
- g_object_unref (ebma);
- }
+ password = e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD);
+ ebbm_connect_user (ebma, cancellable, password, error);
}
}
@@ -588,11 +600,14 @@ ebbm_set_online (EBookBackend *backend, gboolean is_online)
{
EBookBackendMAPI *ebma = E_BOOK_BACKEND_MAPI (backend);
EBookBackendMAPIPrivate *priv = ebma->priv;
+ ESource *esource;
+ const gchar *krb_sso = NULL;
e_book_backend_notify_online (backend, is_online);
if (e_book_backend_is_opened (backend)) {
e_book_backend_mapi_lock_connection (ebma);
+ esource = e_book_backend_get_source (E_BOOK_BACKEND (ebma));
if (!is_online) {
e_book_backend_notify_readonly (backend, TRUE);
ebbm_notify_connection_status (ebma, FALSE);
@@ -603,8 +618,19 @@ ebbm_set_online (EBookBackend *backend, gboolean is_online)
}
} else {
ebbm_notify_connection_status (ebma, TRUE);
- if (!priv->conn)
- e_book_backend_notify_auth_required (backend, TRUE, NULL);
+ if (!priv->conn) {
+ krb_sso = e_source_get_property (esource,
+ "kerberos");
+ if (!krb_sso
+ || !g_str_equal (krb_sso, "required")) {
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
+ } else {
+ ebbm_connect_user (ebma, NULL, NULL,
+ NULL);
+ e_book_backend_notify_opened (backend,
+ NULL);
+ }
+ }
}
e_book_backend_mapi_unlock_connection (ebma);
diff --git a/src/calendar/Makefile.am b/src/calendar/Makefile.am
index 8a457b6..f29f072 100644
--- a/src/calendar/Makefile.am
+++ b/src/calendar/Makefile.am
@@ -5,7 +5,8 @@ AM_CPPFLAGS = \
$(LIBEBACKEND_CFLAGS) \
$(LIBECAL_CFLAGS) \
$(LIBEDATACAL_CFLAGS) \
- $(LIBMAPI_CFLAGS)
+ $(LIBMAPI_CFLAGS) \
+ $(CAMEL_CFLAGS)
ecal_backend_LTLIBRARIES = libecalbackendmapi.la
@@ -20,7 +21,8 @@ libecalbackendmapi_la_LIBADD = \
$(LIBEBACKEND_LIBS) \
$(LIBECAL_LIBS) \
$(LIBEDATACAL_LIBS) \
- $(LIBMAPI_LIBS)
+ $(LIBMAPI_LIBS) \
+ $(CAMEL_LIBS)
libecalbackendmapi_la_LDFLAGS = \
-module -avoid-version $(NO_UNDEFINED)
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index a91ab4b..790b096 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -1221,13 +1221,63 @@ ecbm_connect (ECalBackendMAPI *cbmapi, GError **perror)
}
static void
+ecbm_connect_user (ECalBackend *backend, GCancellable *cancellable, const gchar *password, GError **perror)
+{
+ ECalBackendMAPI *cbmapi;
+ ECalBackendMAPIPrivate *priv;
+ ExchangeMapiConnection *old_conn;
+ GError *mapi_error = NULL;
+
+ g_static_mutex_lock (&auth_mutex);
+
+ cbmapi = E_CAL_BACKEND_MAPI (backend);
+ priv = cbmapi->priv;
+
+ old_conn = priv->conn;
+
+ priv->conn = exchange_mapi_connection_new (priv->profile, password, &mapi_error);
+ if (!priv->conn) {
+ priv->conn = exchange_mapi_connection_find (priv->profile);
+ if (priv->conn
+ && !exchange_mapi_connection_connected (priv->conn)) {
+ exchange_mapi_connection_reconnect (priv->conn, password, &mapi_error);
+ }
+ }
+
+ if (old_conn)
+ g_object_unref (old_conn);
+
+ if (priv->conn && exchange_mapi_connection_connected (priv->conn)) {
+ /* Success */;
+ } else {
+ mapi_error_to_edc_error (perror, mapi_error, AuthenticationFailed, NULL);
+ if (mapi_error)
+ g_error_free (mapi_error);
+ g_static_mutex_unlock (&auth_mutex);
+ return;
+ }
+
+ if (mapi_error) {
+ mapi_error_to_edc_error (perror, mapi_error, AuthenticationFailed, NULL);
+ g_error_free (mapi_error);
+ g_static_mutex_unlock (&auth_mutex);
+ return;
+ }
+
+ g_static_mutex_unlock (&auth_mutex);
+
+ ecbm_connect (cbmapi, perror);
+}
+
+
+static void
ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
ECalBackendMAPI *cbmapi;
ECalBackendMAPIPrivate *priv;
ESource *esource;
const gchar *fid = NULL;
- const gchar *cache_dir;
+ const gchar *cache_dir, *krb_sso = NULL;
uint32_t olFolder = 0;
if (e_cal_backend_is_opened (E_CAL_BACKEND (backend))) {
@@ -1312,58 +1362,29 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
exchange_mapi_util_mapi_id_from_string (fid, &priv->fid);
priv->olFolder = olFolder;
+ krb_sso = e_source_get_property (esource, "kerberos");
g_mutex_unlock (priv->mutex);
e_cal_backend_notify_online (backend, TRUE);
e_cal_backend_notify_readonly (backend, priv->read_only);
- e_cal_backend_notify_auth_required (backend, TRUE, NULL);
+
+ if (!krb_sso || !g_str_equal (krb_sso, "required")) {
+ e_cal_backend_notify_auth_required (backend, TRUE, NULL);
+ } else {
+ ecbm_connect_user (backend, cancellable, NULL, perror);
+ e_cal_backend_notify_opened (backend, NULL);
+ }
}
static void
ecbm_authenticate_user (ECalBackend *backend, GCancellable *cancellable, ECredentials *credentials, GError **perror)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- ExchangeMapiConnection *old_conn;
- GError *mapi_error = NULL;
+ const gchar *password;
g_static_mutex_lock (&auth_mutex);
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
-
- old_conn = priv->conn;
-
- priv->conn = exchange_mapi_connection_new (priv->profile, e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), &mapi_error);
- if (!priv->conn) {
- priv->conn = exchange_mapi_connection_find (priv->profile);
- if (priv->conn && !exchange_mapi_connection_connected (priv->conn))
- exchange_mapi_connection_reconnect (priv->conn, e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), &mapi_error);
- }
-
- if (old_conn)
- g_object_unref (old_conn);
-
- if (priv->conn && exchange_mapi_connection_connected (priv->conn)) {
- /* Success */;
- } else {
- mapi_error_to_edc_error (perror, mapi_error, AuthenticationFailed, NULL);
- if (mapi_error)
- g_error_free (mapi_error);
- g_static_mutex_unlock (&auth_mutex);
- return;
- }
-
- if (mapi_error) {
- mapi_error_to_edc_error (perror, mapi_error, AuthenticationFailed, NULL);
- g_error_free (mapi_error);
- g_static_mutex_unlock (&auth_mutex);
- return;
- }
-
+ password = e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD);
g_static_mutex_unlock (&auth_mutex);
-
- ecbm_connect (cbmapi, perror);
+ ecbm_connect_user (backend, cancellable, password, perror);
}
static gboolean
@@ -2459,7 +2480,9 @@ ecbm_set_online (ECalBackend *backend, gboolean is_online)
{
ECalBackendMAPI *cbmapi;
ECalBackendMAPIPrivate *priv;
+ ESource *esource = NULL;
gboolean re_open = FALSE;
+ const gchar *krb_sso = NULL;
cbmapi = E_CAL_BACKEND_MAPI (backend);
priv = cbmapi->priv;
@@ -2470,14 +2493,18 @@ ecbm_set_online (ECalBackend *backend, gboolean is_online)
g_mutex_lock (priv->mutex);
+ esource = e_cal_backend_get_source (E_CAL_BACKEND (cbmapi));
+ krb_sso = e_source_get_property (esource, "kerberos");
re_open = (e_cal_backend_is_online (backend) ? 1 : 0) < (is_online ? 1 : 0);
e_cal_backend_notify_online (backend, is_online);
priv->mode_changed = TRUE;
if (is_online) {
priv->read_only = FALSE;
- if (e_cal_backend_is_opened (backend) && re_open)
+ if (e_cal_backend_is_opened (backend) && re_open
+ && ! (krb_sso && g_str_equal (krb_sso, "required"))) {
e_cal_backend_notify_auth_required (backend, TRUE, NULL);
+ }
} else {
priv->read_only = TRUE;
}
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index f0d4f16..b14ecb8 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -1634,56 +1634,75 @@ mapi_get_name(CamelService *service, gboolean brief)
}
static gboolean
+mapi_prompt_pass_creds (CamelService *service, CamelURL *url, const gchar *reason, GError **error) {
+ gchar *prompt;
+ guint32 prompt_flags = CAMEL_SESSION_PASSWORD_SECRET;
+ CamelSession *session = camel_service_get_session (service);
+
+ if (reason && *reason) {
+ /* We need to un-cache the password before prompting again */
+ prompt_flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
+ g_free (url->passwd);
+ url->passwd = NULL;
+ }
+
+ /*To translators : First %s : is the error text or the reason
+ for prompting the user if it is available.
+ Second %s is : Username.
+ Third %s is : Server host name.*/
+ prompt = g_strdup_printf (_("%s Please enter the MAPI password for %s %s"),
+ reason, url->user, url->host);
+ url->passwd =
+ camel_session_get_password (session, service,
+ prompt, "password", prompt_flags, NULL);
+ g_free (prompt);
+
+ if (!url->passwd) {
+ g_set_error (
+ error, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("You did not enter a password."));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
mapi_auth_loop (CamelService *service, GError **error)
{
CamelMapiStore *store = CAMEL_MAPI_STORE (service);
- CamelSession *session;
CamelURL *url;
+ ExchangeMapiProfileData empd = { 0 };
gchar *errbuf = NULL;
- gboolean authenticated = FALSE;
- guint32 prompt_flags = CAMEL_SESSION_PASSWORD_SECRET;
+ gboolean authenticated = FALSE, ret, krb_requested = FALSE;
url = camel_service_get_camel_url (service);
- session = camel_service_get_session (service);
+ exchange_mapi_util_profiledata_from_camelurl (&empd, url);
url->passwd = NULL;
while (!authenticated) {
GError *mapi_error = NULL;
- if (errbuf) {
- /* We need to un-cache the password before prompting again */
- prompt_flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
- g_free (url->passwd);
- url->passwd = NULL;
- }
+ if (!url->passwd) {
+ const gchar *why = errbuf ? errbuf : "";
+
+ if (empd.krb_sso) {
+ if (!krb_requested) {
+ ret = exchange_mapi_util_trigger_krb_auth (&empd, error);
+ krb_requested = TRUE;
+ }
+ } else {
+ ret = mapi_prompt_pass_creds (service, url,
+ why, error);
+ }
- if (!url->passwd ) {
- gchar *prompt;
-
- /*To translators : First %s : is the error text or the reason
- for prompting the user if it is available.
- Second %s is : Username.
- Third %s is : Server host name.*/
- prompt = g_strdup_printf (_("%s Please enter the MAPI password for %s %s"),
- errbuf ? errbuf : "",
- url->user,
- url->host);
- url->passwd =
- camel_session_get_password (session, service,
- prompt, "password", prompt_flags, NULL);
- g_free (prompt);
g_free (errbuf);
errbuf = NULL;
-
- if (!url->passwd) {
- g_set_error (
- error, G_IO_ERROR,
- G_IO_ERROR_CANCELLED,
- _("You did not enter a password."));
- return FALSE;
- }
+ }
+ if (!ret || (error && *error)) {
+ return FALSE;
}
store->priv->conn = exchange_mapi_connection_new (store->priv->profile, url->passwd, &mapi_error);
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index 5dc46a7..54515d0 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -43,7 +43,7 @@
static void register_connection (ExchangeMapiConnection *conn);
static void unregister_connection (ExchangeMapiConnection *conn);
-static gboolean mapi_profile_create (const gchar *username, const gchar *password, const gchar *domain, const gchar *server, guint32 flags, mapi_profile_callback_t callback, gpointer data, GError **perror, gboolean use_locking);
+static gboolean mapi_profile_create (const ExchangeMapiProfileData *empd, mapi_profile_callback_t callback, gconstpointer data, GError **perror, gboolean use_locking);
static struct mapi_session *mapi_profile_load (const gchar *profname, const gchar *password, GError **perror);
static void ema_global_lock (void);
static void ema_global_unlock (void);
@@ -3623,6 +3623,7 @@ static gboolean
try_create_profile_main_thread_cb (struct tcp_data *data)
{
EAccountList *accounts;
+ ExchangeMapiProfileData empd = { 0 };
EIterator *iter;
GConfClient *gconf;
@@ -3634,17 +3635,17 @@ try_create_profile_main_thread_cb (struct tcp_data *data)
EAccount *account = E_ACCOUNT (e_iterator_get (iter));
if (account && account->source && account->source->url && g_ascii_strncasecmp (account->source->url, "mapi://", 7) == 0) {
CamelURL *url = camel_url_new (e_account_get_string (account, E_ACCOUNT_SOURCE_URL), NULL);
- const gchar *domain_name;
+ exchange_mapi_util_profiledata_from_camelurl (&empd,
+ url);
+ /* cast away the const, but promise not to touch it */
+ empd.password = (gchar*)data->password;
- domain_name = camel_url_get_param (url, "domain");
- if (data->password && *data->password && domain_name && *domain_name && url->user && *url->user && url->host && *url->host) {
- gchar *profname = exchange_mapi_util_profile_name (url->user, domain_name, url->host, FALSE);
+ if (COMPLETE_PROFILEDATA(&empd)) {
+ gchar *profname = exchange_mapi_util_profile_name (&empd, FALSE);
if (profname && g_str_equal (profname, data->profname)) {
- guint32 cp_flags = (camel_url_get_param (url, "ssl") && g_str_equal (camel_url_get_param (url, "ssl"), "1")) ? CREATE_PROFILE_FLAG_USE_SSL : CREATE_PROFILE_FLAG_NONE;
-
/* do not use locking here, because when this is called then other thread is holding the lock */
- data->has_profile = mapi_profile_create (url->user, data->password, domain_name, url->host, cp_flags, NULL, NULL, NULL, FALSE);
+ data->has_profile = mapi_profile_create (&empd, NULL, NULL, NULL, FALSE);
g_free (profname);
camel_url_free (url);
@@ -3673,8 +3674,6 @@ try_create_profile (const gchar *profname, const gchar *password)
g_return_val_if_fail (profname != NULL, FALSE);
g_return_val_if_fail (*profname != 0, FALSE);
- g_return_val_if_fail (password != NULL, FALSE);
- g_return_val_if_fail (*password != 0, FALSE);
data.profname = profname;
data.password = password;
@@ -3841,9 +3840,8 @@ create_profile_fallback_callback (struct SRowSet *rowset, gconstpointer data)
}
static gboolean
-mapi_profile_create (const gchar *username, const gchar *password, const gchar *domain,
- const gchar *server, guint32 flags,
- mapi_profile_callback_t callback, gpointer data,
+mapi_profile_create (const ExchangeMapiProfileData *empd,
+ mapi_profile_callback_t callback, gconstpointer data,
GError **perror,
gboolean use_locking)
{
@@ -3855,17 +3853,18 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
if (!callback) {
callback = create_profile_fallback_callback;
- data = (gpointer) username;
+ data = (gpointer) empd->username;
}
/*We need all the params before proceeding.*/
- e_return_val_mapi_error_if_fail (username && *username && password && *password &&
- domain && *domain && server && *server, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (COMPLETE_PROFILEDATA(empd),
+ MAPI_E_INVALID_PARAMETER, FALSE);
if (use_locking)
g_static_rec_mutex_lock (&profile_mutex);
- g_debug ("Create profile with %s %s %s\n", username, domain, server);
+ g_debug ("Create profile with %s %s %s\n", empd->username,
+ empd->domain, empd->server);
if (!ensure_mapi_init_called (perror)) {
if (use_locking)
@@ -3873,14 +3872,14 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
return FALSE;
}
- profname = exchange_mapi_util_profile_name (username, domain, server, TRUE);
+ profname = exchange_mapi_util_profile_name (empd, TRUE);
/* Delete any existing profiles with the same profilename */
ms = DeleteProfile (mapi_ctx, profname);
/* don't bother to check error - it would be valid if we got an error */
- ms = CreateProfile (mapi_ctx, profname, username, password,
- OC_PROFILE_NOPASSWORD);
+ ms = CreateProfile (mapi_ctx, profname, empd->username,
+ empd->password, OC_PROFILE_NOPASSWORD);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "CreateProfile", ms);
goto cleanup;
@@ -3889,11 +3888,20 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
#define add_string_attr(_prof,_aname,_val) \
mapi_profile_add_string_attr (mapi_ctx, _prof, _aname, _val)
- add_string_attr (profname, "binding", server);
+ add_string_attr (profname, "binding", empd->server);
add_string_attr (profname, "workstation", workstation);
- add_string_attr (profname, "domain", domain);
- if ((flags & CREATE_PROFILE_FLAG_USE_SSL) != 0)
+ if (empd->krb_sso) {
+ /* note: domain and realm are intentially not added to
+ * the libmapi profile in the case of SSO enabled,
+ * as it changes the behavior, and breaks SSO support. */
+ add_string_attr (profname, "kerberos", "yes");
+ } else {
+ /* only add domain if !kerberos SSO */
+ add_string_attr (profname, "domain", empd->domain);
+ }
+
+ if (empd->use_ssl)
add_string_attr (profname, "seal", "true");
/* This is only convenient here and should be replaced at some point */
@@ -3905,7 +3913,7 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
/* Login now */
g_debug("Logging into the server... ");
- ms = MapiLogonProvider (mapi_ctx, &session, profname, password,
+ ms = MapiLogonProvider (mapi_ctx, &session, profname, empd->password,
PROVIDER_ID_NSPI);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "MapiLogonProvider", ms);
@@ -3915,7 +3923,7 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
}
g_debug("MapiLogonProvider : succeeded \n");
- ms = ProcessNetworkProfile (session, username, callback, data);
+ ms = ProcessNetworkProfile (session, empd->username, callback, data);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "ProcessNetworkProfile", ms);
g_debug ("Deleting profile %s ", profname);
@@ -3953,12 +3961,11 @@ mapi_profile_create (const gchar *username, const gchar *password, const gchar *
}
gboolean
-exchange_mapi_create_profile (const gchar *username, const gchar *password, const gchar *domain,
- const gchar *server, guint32 flags,
- mapi_profile_callback_t callback, gpointer data,
+exchange_mapi_create_profile (ExchangeMapiProfileData *empd,
+ mapi_profile_callback_t callback, gconstpointer data,
GError **perror)
{
- return mapi_profile_create (username, password, domain, server, flags, callback, data, perror, TRUE);
+ return mapi_profile_create (empd, callback, data, perror, TRUE);
}
gboolean
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index d5eee38..9ee9d8a 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -237,14 +237,23 @@ gboolean exchange_mapi_connection_events_unsubscribe (ExchangeMapiConnection *c
/* profile functions */
-enum {
- CREATE_PROFILE_FLAG_NONE = 0,
- CREATE_PROFILE_FLAG_USE_SSL = (1 << 0)
-};
-
-gboolean exchange_mapi_create_profile (const gchar *username, const gchar *password,
- const gchar *domain, const gchar *server, guint32 flags,
- mapi_profile_callback_t cb, gpointer data, GError **perror);
+typedef struct {
+ const gchar *username;
+ gchar *password;
+ const gchar *domain;
+ const gchar *server;
+ gboolean use_ssl;
+ gboolean krb_sso;
+ const gchar *krb_realm;
+} ExchangeMapiProfileData;
+
+#define COMPLETE_PROFILEDATA(x) \
+ ((x)->username && *(x)->username && (x)->server && *(x)->server \
+ && (((x)->domain && *(x)->domain && (x)->password && *(x)->password) \
+ || ((x)->krb_sso && (x)->krb_realm && *(x)->krb_realm)))
+
+gboolean exchange_mapi_create_profile (ExchangeMapiProfileData *profile,
+ mapi_profile_callback_t cb, gconstpointer data, GError **perror);
gboolean exchange_mapi_delete_profile (const gchar *profile, GError **perror);
void exchange_mapi_rename_profile (const gchar *old_name, const gchar *new_name);
diff --git a/src/libexchangemapi/exchange-mapi-utils.c b/src/libexchangemapi/exchange-mapi-utils.c
index e712c5f..bb9ea69 100644
--- a/src/libexchangemapi/exchange-mapi-utils.c
+++ b/src/libexchangemapi/exchange-mapi-utils.c
@@ -41,6 +41,10 @@
#define gmtime_r(tp,tmp) (gmtime(tp)?(*(tmp)=*gmtime(tp),(tmp)):0)
#endif
+/* Used for callout to krb5-auth-dialog */
+#define KRB_DBUS_PATH "/org/gnome/KrbAuthDialog"
+#define KRB_DBUS_INTERFACE "org.gnome.KrbAuthDialog"
+
inline gchar *
exchange_mapi_util_mapi_id_to_string (mapi_id_t id)
{
@@ -1020,10 +1024,93 @@ exchange_crlf_to_lf (const gchar *in)
}
/**
+ * exchange_mapi_util_profiledata_from_camelurl:
+ * @empd: destination for profile settings
+ * @url: CamelURL with account settings
+ *
+ * Sets the members of an ExchangeMapiProfileData instance to
+ * reflect the account settings listed in the corresponding
+ * CamelURL pointer.
+ *
+ * @note: no allocation is done, so do not free the CamelUrl pointer and
+ * the respective underlying pointers until you no longer need the
+ * profile data.
+ **/
+void
+exchange_mapi_util_profiledata_from_camelurl (ExchangeMapiProfileData *empd, const CamelURL *url)
+{
+ const gchar *use_ssl = NULL, *use_krb = NULL;
+ CamelURL *promise_its_const = (CamelURL*)url; /* :) */
+ empd->username = promise_its_const->user;
+ empd->server = promise_its_const->host;
+
+ use_ssl = camel_url_get_param (promise_its_const, "ssl");
+ empd->use_ssl = (use_ssl && g_str_equal (use_ssl, "1"));
+ empd->domain = camel_url_get_param (promise_its_const, "domain");
+ use_krb = camel_url_get_param (promise_its_const, "kerberos");
+ empd->krb_sso = (use_krb && g_str_equal (use_krb, "required"));
+ empd->krb_realm = camel_url_get_param (promise_its_const, "realm");
+}
+
+gboolean
+exchange_mapi_util_trigger_krb_auth (const ExchangeMapiProfileData *empd, GError **error) {
+ gint success = FALSE;
+ GError *local_error = NULL;
+ GDBusConnection *connection;
+ GDBusMessage *message, *reply;
+ gchar *name;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error);
+ if (local_error) {
+ g_warning ("could not get system bus: %s\n",
+ local_error->message);
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ g_dbus_connection_set_exit_on_close (connection, FALSE);
+ /* Create a new message on the KRB_DBUS_INTERFACE */
+ message = g_dbus_message_new_method_call (KRB_DBUS_INTERFACE,
+ KRB_DBUS_PATH,
+ KRB_DBUS_INTERFACE,
+ "acquireTgt");
+ if (!message) {
+ g_object_unref (connection);
+ return FALSE;
+ }
+
+ /* Appends the data as an argument to the message */
+ name = g_strdup_printf ("%s %s", empd->username, empd->krb_realm);
+ g_dbus_message_set_body (message, g_variant_new ("(s)", name));
+
+ /* Sends the message: Have a 300 sec wait timeout */
+ reply = g_dbus_connection_send_message_with_reply_sync (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 300 * 1000, NULL, NULL, &local_error);
+ g_free (name);
+
+ if (local_error) {
+ g_warning ("%s: %s\n", G_STRFUNC, local_error->message);
+ g_propagate_error (error, local_error);
+ }
+
+ if (reply) {
+ GVariant *body = g_dbus_message_get_body (reply);
+ if (body) {
+ g_variant_get (body, "(b)", &success);
+ }
+ g_object_unref (reply);
+ }
+
+ /* Free the message */
+ g_object_unref (message);
+ g_object_unref (connection);
+
+ return success && !local_error;
+}
+
+
+/**
* exchange_mapi_util_profile_name:
- * @username: User name of the profile
- * @domain: Domain name of the profile
- * @hostname: Server host name
+ * @empd: profile information used to construct the name
* @migrate: whether migrate old profile name to a new one
*
* Constructs profile name from given parameters and
@@ -1031,18 +1118,20 @@ exchange_crlf_to_lf (const gchar *in)
* rename old profile name string to a new name, if requested.
**/
gchar *
-exchange_mapi_util_profile_name (const gchar *username, const gchar *domain, const gchar *hostname, gboolean migrate)
+exchange_mapi_util_profile_name (const ExchangeMapiProfileData *empd, gboolean migrate)
{
gchar *res;
- res = g_strdup_printf ("%s %s@%s", username, domain, hostname);
+ res = g_strdup_printf ("%s %s@%s", empd->username, empd->domain,
+ empd->server);
res = g_strcanon (res, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -", '_');
if (migrate) {
/* expects MAPIInitialize already called! */
gchar *old_name;
- old_name = g_strdup_printf ("%s %s", username, domain);
+ old_name = g_strdup_printf ("%s %s", empd->username,
+ empd->domain);
old_name = g_strcanon (old_name, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@", '_');
exchange_mapi_rename_profile (old_name, res);
diff --git a/src/libexchangemapi/exchange-mapi-utils.h b/src/libexchangemapi/exchange-mapi-utils.h
index 51c32fc..b0ec1c6 100644
--- a/src/libexchangemapi/exchange-mapi-utils.h
+++ b/src/libexchangemapi/exchange-mapi-utils.h
@@ -25,6 +25,7 @@
#define EXCHANGE_MAPI_UTILS_H
#include "exchange-mapi-connection.h"
+#include <camel/camel.h>
gchar * exchange_mapi_util_mapi_id_to_string (mapi_id_t id);
gboolean exchange_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
@@ -58,7 +59,9 @@ gboolean exchange_mapi_util_recip_entryid_decode (ExchangeMapiConnection *conn,
gchar *exchange_lf_to_crlf (const gchar *in);
gchar *exchange_crlf_to_lf (const gchar *in);
-gchar *exchange_mapi_util_profile_name (const gchar *username, const gchar *domain, const gchar *hostname, gboolean migrate);
+void exchange_mapi_util_profiledata_from_camelurl (ExchangeMapiProfileData *empd, const CamelURL *url);
+gchar *exchange_mapi_util_profile_name (const ExchangeMapiProfileData *empd, gboolean migrate);
+gboolean exchange_mapi_util_trigger_krb_auth (const ExchangeMapiProfileData *empd, GError **error);
gboolean exchange_mapi_utils_add_props_to_props_array (TALLOC_CTX *mem_ctx, struct SPropTagArray *props, const uint32_t *prop_ids, guint prop_ids_n_elems);
gboolean exchange_mapi_utils_add_named_ids_to_props_array (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, ResolveNamedIDsData *named_ids_list, guint named_ids_n_elems);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]