"Fossies" - the Fresh Open Source Software archive 
Member "evolution-brutus-1.2.35/server/brutus_util.c" of archive evolution-brutus-1.2.35.tar.gz:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Implementation file for Brutus utility functions.
* Copyright (C) 2005-2007 OMC Denmark ApS.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/* system includes */
#include <glib.h>
#include <glib/gprintf.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <libedataserver/e-source-list.h>
#include <libedataserver/md5-utils.h>
#include <brutus-keyring.h>
#include <brutus-keyringd.h>
/* evolution-brutus includes */
#include <idl_output/return_codes.h>
#include <session/brutusd.h>
#include <server/brutus_conv.h>
#include <log/brutus-logd.h>
#include <servant_impl/BrutusCheck.h>
/* Lorica */
#include "ReferenceMapper.h"
#include "brutus_corba.h"
#include "brutus_mapi.h"
#include "brutus_uuid.h"
#include "brutus_util.h"
#define BRUTUS_REQ_MAJOR (2)
#define BRUTUS_REQ_MINOR (0)
#define BRUTUS_REQ_MICRO (0)
#define BRUTUS_REQ_RELEASE_TAG (0)
gboolean
brutus_server_version_OK(int major,
int minor,
int micro,
int release_tag)
{
return ((BRUTUS_REQ_MAJOR == major)
&& (BRUTUS_REQ_MINOR == minor));
}
void brutus_for_each_free(gpointer data,
gpointer user_data)
{
free(data);
}
void brutus_for_each_g_free(gpointer data,
gpointer user_data)
{
g_free(data);
}
int brutus_timezone_to_gmt_offset(long time_zone_offset)
{
int tz = (-1) * time_zone_offset;
return (((tz/60/60) * 100) + (tz/60 % 60));
}
static gboolean
brutus_get_e_source_list(ESourceList **sources,
const enum E_SOURCE_BRUTUS_TYPE type)
{
gboolean retv = TRUE;
GConfClient *gconf = gconf_client_get_default();
if (!gconf)
return FALSE;
switch (type) {
case E_SOURCE_BRUTUS_CALENDAR:
*sources = e_source_list_new_for_gconf(gconf, "/apps/evolution/calendar/sources");
break;
case E_SOURCE_BRUTUS_TASKS:
*sources = e_source_list_new_for_gconf(gconf, "/apps/evolution/tasks/sources");
break;
case E_SOURCE_BRUTUS_NOTES:
*sources = e_source_list_new_for_gconf(gconf, "/apps/evolution/memos/sources");
break;
case E_SOURCE_BRUTUS_ADDRESSBOOK_PAB:
case E_SOURCE_BRUTUS_ADDRESSBOOK_GAL:
*sources = e_source_list_new_for_gconf(gconf, "/apps/evolution/addressbook/sources");
break;
default:
retv = FALSE;
}
g_object_unref(gconf);
return retv;
}
static const char*
brutus_get_account_sub_type(const enum E_SOURCE_BRUTUS_TYPE e_type)
{
// create relative uri
switch (e_type) {
case E_SOURCE_BRUTUS_CALENDAR:
return "EVENTS";
break;
case E_SOURCE_BRUTUS_TASKS:
return "TODOS";
break;
case E_SOURCE_BRUTUS_NOTES:
return "NOTES";
break;
case E_SOURCE_BRUTUS_ADDRESSBOOK_PAB:
case E_SOURCE_BRUTUS_ADDRESSBOOK_GAL:
return "ADDRESSBOOK";
break;
default:
g_assert_not_reached();
}
return "";
}
gboolean
brutus_add_account(const enum E_SOURCE_BRUTUS_TYPE e_type,
const char *account_name,
const char *mapi_profile,
const char *exchange_server,
const char *windows_user,
const char *effective_mailbox,
const char *exchange_mailbox,
const char *exchange_mailbox_dn,
const char *exchange_mailbox_email,
const char *windows_domain,
const char *brutus_server,
const guint16 brutus_port,
const gboolean expect_other_clients,
int auto_check_timeout)
{
gboolean retv = FALSE;
gboolean unref_group = FALSE;
ESourceList *source_list = NULL;
ESourceGroup *group = NULL;
ESource *source = NULL;
char *relative_uri = NULL;
char *timeout = NULL;
const char *sub_type = NULL;
char brutus_kind[5] = { '\0' };
char port[8] = { '\0' };
if (0 > snprintf(port, sizeof(port), "%hu", brutus_port)) {
d("Invalid Brutus port number");
goto out;
}
if (-1 == auto_check_timeout)
auto_check_timeout = 10;
timeout = g_strdup_printf("%d", auto_check_timeout);
if (!timeout) {
d("No memory");
goto out;
}
// get list of groups
if (!brutus_get_e_source_list(&source_list, e_type)) {
d("Could not get source list from GConf");
goto out;
}
// create group
group = e_source_list_peek_group_by_name(source_list, "Brutus");
if (!group) {
group = e_source_group_new("Brutus", "brutus://");
if (!group) {
d("No memory");
goto out;
}
unref_group = TRUE;
if (!e_source_list_add_group(source_list, group, -1)) {
d("Could not add Brutus source group");
goto out;
} else {
e_source_list_sync(source_list, NULL);
}
}
// create relative uri
sub_type = brutus_get_account_sub_type(e_type);
relative_uri = g_strdup_printf("%s\\%s@%s:%s:__%s",
windows_domain,
windows_user,
exchange_server,
effective_mailbox,
sub_type);
if (!relative_uri) {
d("No memory");
goto out;
}
// check for presence of source
source = e_source_group_peek_source_by_name(group, account_name);
if (source) {
if (!g_ascii_strcasecmp(mapi_profile, e_source_get_property(source, "mapi_profile"))) {
retv = TRUE;
goto out;
}
} else { // create source
source = e_source_new(account_name, relative_uri);
if (!source) {
d("Could not create new source");
goto out;
}
}
// get the stringified account type
g_sprintf(brutus_kind, "%u", brutus_e_type_to_unsigned_int(e_type));
// set properties
e_source_set_color(source, 0x3F8D46); // 42tools green
e_source_set_property(source, "mapi_profile", mapi_profile);
e_source_set_property(source, "exchange_server", exchange_server);
e_source_set_property(source, "windows_user", windows_user);
e_source_set_property(source, "effective_mailbox", effective_mailbox);
e_source_set_property(source, "exchange_mailbox", (exchange_mailbox ? exchange_mailbox : ""));
e_source_set_property(source, "exchange_mailbox_dn", (exchange_mailbox_dn ? exchange_mailbox_dn : ""));
e_source_set_property(source, "exchange_mailbox_email", (exchange_mailbox_email ? exchange_mailbox_email : ""));
e_source_set_property(source, "windows_domain", windows_domain);
e_source_set_property(source, "brutus_server", brutus_server);
e_source_set_property(source, "brutus_port", port);
e_source_set_property(source, "brutus_kind", brutus_kind);
e_source_set_property(source, "expect_other_clients", expect_other_clients ? "1" : "0");
e_source_set_property(source, "auto_check_timeout", timeout);
if (!e_source_group_add_source(group, source, -1)) {
d("Could not add source to group");
goto out;
}
if (!e_source_list_sync(source_list, NULL)) {
d("Could not sync source list");
goto out;
}
retv = TRUE;
out:
if (timeout)
g_free(timeout);
if (relative_uri)
g_free(relative_uri);
if (source)
g_object_unref(source);
if (group && unref_group)
g_object_unref(group);
if (source_list)
g_object_unref(source_list);
return retv;
}
void
brutus_remove_account(const enum E_SOURCE_BRUTUS_TYPE e_type,
const char *account_name,
const char *mapi_profile)
{
ESourceList *source_list = NULL;
ESourceGroup *group = NULL;
ESource *source = NULL;
// get list of groups
if (!brutus_get_e_source_list(&source_list, e_type)) {
d("Could not get source list from GConf");
goto out;
}
// get group
group = e_source_list_peek_group_by_name(source_list, "Brutus");
if (!group)
goto out;
// check for presence of source
source = e_source_group_peek_source_by_name(group, account_name);
if (source) {
if (!g_ascii_strcasecmp(mapi_profile, e_source_get_property(source, "mapi_profile")))
e_source_group_remove_source(group, source);
}
if (!e_source_list_sync(source_list, NULL))
d("Could not sync source list");
out:
if (source)
g_object_unref(source);
if (source_list)
g_object_unref(source_list);
}
static CORBA_ORB
create_orb(CORBA_Environment *ev)
{
CORBA_ORB orb = CORBA_OBJECT_NIL;
int init_argc = 4;
char **init_argv = (char**)malloc(sizeof(char*) * (init_argc));
if (!init_argv)
return CORBA_OBJECT_NIL;
init_argv[0] = strdup("DUMMY_ARGV0");
// IPv4 - needed to interoperate with clients
init_argv[1] = "--ORBIIOPIPv4=1";
// IPv6 - better to switch it off if we do not use it
init_argv[2] = "--ORBIIOPIPv6=0";
// Explicitly force ORBit2 to be local only
init_argv[3] = "--ORBLocalOnly=1";
// initialize the ORB
orb = CORBA_ORB_init(&init_argc, init_argv, "brutus-util_orb_orbit-io-thread", ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
orb = CORBA_OBJECT_NIL;
}
free(init_argv[0]);
free(init_argv);
return orb;
}
static BRUTUS_BrutusKeyring
get_keyring_ref(CORBA_ORB orb)
{
gchar *ref_path = NULL;
BRUTUS_BrutusKeyring keyring = CORBA_OBJECT_NIL;
CORBA_boolean cb = CORBA_FALSE;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
cb = CORBA_Object_is_nil((CORBA_Object)orb, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (cb) {
d("ORB is NIL");
goto out;
}
ref_path = g_strconcat(getenv("HOME"), "/", BRUTUS_KEYRINGD_REF_FILE_NAME, NULL);
if (!ref_path)
goto out;
d("Before getting keyring ref from file");
keyring = brutus_object_ref_from_file(orb, ref_path);
g_free(ref_path);
cb = CORBA_Object_is_nil((CORBA_Object)keyring, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (cb) {
d("Could not get the Brutus Keyring reference");
goto out;
}
out:
CORBA_exception_free(ev);
return keyring;
}
static void
brutus_forget_account_password(const char *mapi_profile)
{
BRUTUS_BrutusKeyring keyring = CORBA_OBJECT_NIL;
CORBA_boolean cb = CORBA_TRUE;
CORBA_ORB orb = CORBA_OBJECT_NIL;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
orb = create_orb(ev);
keyring = get_keyring_ref(orb);
cb = CORBA_Object_is_nil((CORBA_Object)keyring, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (cb)
goto out;
BRUTUS_BrutusKeyring_delSecret(keyring, mapi_profile, ev);
out:
CORBA_Object_release((CORBA_Object)keyring, ev);
CORBA_Object_release((CORBA_Object)orb, ev);
CORBA_exception_free(ev);
return;
}
static void
brutus_set_account_password(const char *mapi_profile,
const char *password)
{
BRUTUS_BrutusKeyring_KeyringResult keyring_retv = BRUTUS_BrutusKeyring_failed;
BRUTUS_BrutusKeyring_KeyringData secret;
BRUTUS_BrutusKeyring keyring = CORBA_OBJECT_NIL;
CORBA_boolean cb = CORBA_TRUE;
CORBA_ORB orb = CORBA_OBJECT_NIL;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
orb = create_orb(ev);
keyring = get_keyring_ref(orb);
cb = CORBA_Object_is_nil((CORBA_Object)keyring, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (cb)
goto out;
if (!password)
goto out;
else {
secret._maximum = strlen(password)+1;
secret._length = secret._maximum;
secret._buffer = BRUTUS_BrutusKeyring_KeyringData_allocbuf(secret._maximum);
if (!secret._buffer)
goto out;
}
keyring_retv = BRUTUS_BrutusKeyring_setSecret(keyring, mapi_profile, &secret, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (BRUTUS_BrutusKeyring_success == keyring_retv)
out:
if (secret._buffer)
CORBA_free(secret._buffer);
CORBA_Object_release((CORBA_Object)keyring, ev);
CORBA_Object_release((CORBA_Object)orb, ev);
CORBA_exception_free(ev);
return;
}
/*
* This will retrieve the Brutus account password for a specified MAPI profile.
*/
static char*
brutus_get_account_password(const char *mapi_profile)
{
BRUTUS_BrutusKeyring_KeyringResult keyring_retv = BRUTUS_BrutusKeyring_failed;
BRUTUS_BrutusKeyring_KeyringData *secret = NULL;
BRUTUS_BrutusKeyring keyring = CORBA_OBJECT_NIL;
CORBA_boolean cb = CORBA_TRUE;
CORBA_ORB orb = CORBA_OBJECT_NIL;
CORBA_Environment ev[1];
char *retv = NULL;
int status;
char *argv[] = {
LIBEXECDIR "/brutus-query-password",
"-set_passphrase",
NULL,
};
CORBA_exception_init(ev);
orb = create_orb(ev);
keyring = get_keyring_ref(orb);
cb = CORBA_Object_is_nil((CORBA_Object)keyring, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (cb)
goto out;
keyring_retv = BRUTUS_BrutusKeyring_getSecret(keyring, mapi_profile, &secret, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (BRUTUS_BrutusKeyring_set_passphrase == keyring_retv) {
g_spawn_sync(NULL,
argv,
NULL,
G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
NULL,
&status,
NULL);
if (EXIT_SUCCESS != status)
goto out;
}
keyring_retv = BRUTUS_BrutusKeyring_getSecret(keyring, mapi_profile, &secret, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (BRUTUS_BrutusKeyring_success == keyring_retv)
retv = strdup((const char*)secret->_buffer);
out:
if (secret)
CORBA_free(secret);
CORBA_Object_release((CORBA_Object)keyring, ev);
CORBA_Object_release((CORBA_Object)orb, ev);
CORBA_exception_free(ev);
return retv;
}
static char*
brutus_get_password(const char *prompt,
const char *mapi_profile)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char *password = NULL;
int status;
char *argv[] = {
LIBEXECDIR "/brutus-query-password",
"-set_password",
(char*)prompt,
(char*)mapi_profile,
NULL,
};
// only one password query dialog at any one time
pthread_mutex_lock(&mutex);
d("libexecdir = " LIBEXECDIR);
password = brutus_get_account_password(mapi_profile); // from keyring
if (!password) { // not present, query user
d("Could not retrieve password from keyring - querying user");
g_spawn_sync(NULL,
argv,
NULL,
G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
NULL,
&status,
NULL);
if (EXIT_SUCCESS != status)
goto out;
password = brutus_get_account_password(mapi_profile); // try the keyring again
}
out:
pthread_mutex_unlock(&mutex);
return password;
}
static Lorica_ReferenceMapper
get_lorica(void)
{
CORBA_char *corbaloc_str[512] = { '\0' };
CORBA_boolean cb = CORBA_TRUE;
CORBA_ORB orb = CORBA_OBJECT_NIL;
Lorica_ReferenceMapper mapper = CORBA_OBJECT_NIL;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
orb = create_orb(ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_lorica;
}
snprintf((char*)corbaloc_str, sizeof(corbaloc_str), "corbaloc:iiop:localhost:%u/%s", Lorica_ReferenceMapper_lorica_in_port, Lorica_ReferenceMapper_IOR_TABLE_KEY);
mapper = (Lorica_ReferenceMapper)CORBA_ORB_string_to_object(orb, (CORBA_char*)corbaloc_str, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_lorica;
}
cb = CORBA_Object_is_nil((CORBA_Object)mapper, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_lorica;
}
if (cb)
goto no_lorica;
cb = CORBA_Object_non_existent((CORBA_Object)mapper, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_lorica;
}
if (cb)
goto no_lorica;
goto lorica_ok;
no_lorica:
d("no_lorica");
CORBA_Object_release((CORBA_Object)orb, ev);
CORBA_exception_free(ev);
return CORBA_OBJECT_NIL;
lorica_ok:
d("lorica_ok");
CORBA_Object_release((CORBA_Object)orb, ev);
CORBA_exception_free(ev);
return mapper;
}
gboolean
brutus_logon_loop(BRUTUS_BrutusLogOn brutus_logon,
BRUTUS_BrutusCheck lifeline,
BRUTUS_IMAPISession *mapi_session,
CORBA_unsigned_long *instance_id,
const char *brutus_logon_corbaloc,
const char *prompt,
const char *err_prompt,
const char *windows_user,
const char *windows_domain,
const char *exchange_mailbox,
const char *exchange_mailbox_dn,
const char *exchange_mailbox_email,
const char *exchange_server,
char **mapi_profile,
char **effective_mailbox)
{
BRUTUS_BrutusLogOn brutus_logon_mapped = CORBA_OBJECT_NIL;
Lorica_ReferenceMapper lorica = CORBA_OBJECT_NIL;
CORBA_boolean cb = CORBA_TRUE;
gboolean retv = FALSE;
gboolean ref_mapped = FALSE;
BRUTUS_BRESULT br = BRUTUS_BRUTUS_MAPI_E_LOGON_FAILED;
char *password = NULL;
uuid_str_t uuid = { '\0' };
const size_t mailbox_opts_len = 5;
char *mailbox_opts[mailbox_opts_len];
size_t idx = 0;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
cb = CORBA_Object_is_nil((CORBA_Object)brutus_logon, ev);
if (ORBIT2_EX(ev) || cb) {
d("No valid logon reference");
goto out;
}
mailbox_opts[0] = *effective_mailbox;
mailbox_opts[1] = (exchange_mailbox_email && strlen(exchange_mailbox_email)) ? g_strdup_printf("SMTP:%s", exchange_mailbox_email) : g_strdup("");
mailbox_opts[2] = (exchange_mailbox && strlen(exchange_mailbox)) ? g_strdup(exchange_mailbox) : g_strdup("");
mailbox_opts[3] = (strlen(mailbox_opts[1])) ? g_strdup_printf("=%s", exchange_mailbox) : g_strdup("");
mailbox_opts[4] = (exchange_mailbox_dn && strlen(exchange_mailbox_dn)) ? g_strdup(exchange_mailbox_dn) : g_strdup("");
d(mailbox_opts[0]);
d(mailbox_opts[1]);
d(mailbox_opts[2]);
d(mailbox_opts[3]);
d(mailbox_opts[4]);
d(windows_user);
d(windows_domain);
d(exchange_server);
/* get the password */
password = brutus_get_password(prompt, (const char*)(*mapi_profile));
if (!password) {
d("User canceled or password was all whitespace");
goto out;
} else
d("Recieved password from keyring");
// get a client mapped ref if possible
do {
lorica = get_lorica();
cb = CORBA_Object_is_nil((CORBA_Object)lorica, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_map;
}
if (cb)
goto no_map;
brutus_logon_mapped = Lorica_ReferenceMapper_as_client_with_corbaloc(lorica,
brutus_logon_corbaloc,
"IDL:omc.brutus/BRUTUS/BrutusLogOn:1.0",
ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_map;
}
cb = CORBA_Object_is_nil((CORBA_Object)brutus_logon_mapped, ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto no_map;
}
if (cb)
goto no_map;
ref_mapped = TRUE;
break;
no_map:
brutus_logon_mapped = brutus_logon;
} while (FALSE);
do { // loop indefinitely if password is bad, break for other errors
idx = 0;
do { // loop while resolving the mailbox
if (idx >= mailbox_opts_len)
break;
if (!mailbox_opts[idx] || !strlen(mailbox_opts[idx])) {
idx++;
continue;
}
d((const char*)(*mapi_profile));
d(windows_user);
d(windows_domain);
dfmt2("mailbox_opts[%d] = %s", idx, mailbox_opts[idx]);
br = BRUTUS_BrutusLogOn_Logon(brutus_logon_mapped,
lifeline,
(const char*)(*mapi_profile),
"",
windows_user,
windows_domain,
password,
mailbox_opts[idx],
exchange_server,
BRUTUS_BRUTUS_MAPI_EXPLICIT_PROFILE,
0,
BRUTUS_SERVER_TYPE_EXCHANGE, // or BRUTUS_SERVER_TYPE_DOMINO
instance_id,
mapi_session,
ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
d(brutus_bresult_to_str(br));
switch (br) {
case BRUTUS_BRUTUS_MAPI_E_UNKNOWN_MAILBOX : // could not resolve mailbox
case BRUTUS_BRUTUS_MAPI_E_AMBIGUOUS_RECIP : // could not resolve mailbox
case BRUTUS_BRUTUS_MAPI_E_VERSION : // no support
idx++;
continue;
default :
break;
}
break;
} while (TRUE);
switch (br) {
case BRUTUS_BRUTUS_LIFELINE_TIMEOUT :
d("Lifeline timeout");
goto out;
case BRUTUS_BRUTUS_EXCEPTION_FROM_CLIENT :
d("Possible exception in lifeline servant - exiting from logon loop");
goto out;
case BRUTUS_BRUTUS_INTERNAL_ERROR :
d("Brutus Server internal error");
goto out;
default :
d(brutus_bresult_to_str(br));
break;
}
if (BRUTUS_BRUTUS_MAPI_E_LOGON_FAILED == br) {
g_free(password);
password = NULL;
brutus_forget_account_password((const char*)(*mapi_profile)); // forget bad password
password = brutus_get_password(err_prompt, (const char*)(*mapi_profile));
if (!password) { // user canceled
d("User canceled or password was all whitespace");
goto out;
}
continue;
}
if (BRUTUS_BRUTUS_MAPI_E_NO_ACCESS == br) {
brutus_forget_account_password((const char*)(*mapi_profile)); // forget bad profile
goto create_profile;
}
break;
} while (TRUE);
if (BRUTUS_BRUTUS_S_OK == br) {
retv = TRUE;
goto out;
}
dfmt("BrutusLogOn->Logon() returned %s", brutus_bresult_to_str(br));
if (BRUTUS_BRUTUS_MAPI_E_NOT_INITIALIZED == br)
goto out;
create_profile:
if (BRUTUS_BRUTUS_MAPI_E_NO_ACCESS == br) { // should never happen...
d("MAPI profile name collision, creating a new one...");
brutus_uuid(uuid);
CORBA_free(*mapi_profile);
*mapi_profile = CORBA_string_dup(uuid);
brutus_forget_account_password((const char*)(*mapi_profile)); // forget bad password
brutus_set_account_password((const char*)(*mapi_profile),
password);
dfmt("The new MAPI profile is \"%s\"", *mapi_profile);
}
dfmt("Attempting logon with MAPI profile \"%s\"", *mapi_profile);
do {
br = BRUTUS_BrutusLogOn_Logon(brutus_logon_mapped,
lifeline,
(const char*)(*mapi_profile),
"",
windows_user,
windows_domain,
password,
mailbox_opts[idx],
exchange_server,
BRUTUS_BRUTUS_MAPI_EXPLICIT_PROFILE,
0,
BRUTUS_SERVER_TYPE_EXCHANGE, // or BRUTUS_SERVER_TYPE_DOMINO
instance_id,
mapi_session,
ev);
if (ORBIT2_EX(ev)) {
PRINT_ORBIT2_EX(ev);
goto out;
}
if (BRUTUS_BRUTUS_S_OK != br) {
d(brutus_bresult_to_str(br));
g_free(password);
password = NULL;
brutus_forget_account_password((const char*)(*mapi_profile)); // forget bad password
password = brutus_get_password(err_prompt, (const char*)(*mapi_profile));
if (!password) { // user canceled
d("User canceled or password was all whitespace");
goto out;
}
} else
break;
} while (TRUE);
out:
if (ref_mapped) {
Lorica_ReferenceMapper_remove_client(lorica, (CORBA_Object)brutus_logon_mapped, ev);
CORBA_Object_release((CORBA_Object)lorica, ev);
CORBA_Object_release((CORBA_Object)brutus_logon_mapped, ev);
}
if (BRUTUS_BRUTUS_S_OK == br) {
if (idx) { // new effective mailbox name
if (*effective_mailbox)
CORBA_free(*effective_mailbox);
*effective_mailbox = CORBA_string_dup(mailbox_opts[idx]);
}
dfmt("\"%s\" has logged on", windows_user);
retv = TRUE;
}
CORBA_exception_free(ev);
g_free(password);
// never free mailbox_opts[0]
g_free(mailbox_opts[1]);
g_free(mailbox_opts[2]);
g_free(mailbox_opts[3]);
g_free(mailbox_opts[4]);
return retv;
}
static inline gboolean
brutus_digest_str_is_null(const digest_str_t digest_str)
{
return (('\0' == digest_str[0]) ? TRUE : FALSE);
}
static inline gboolean
brutus_digest_is_null(const digest_t digest)
{
static const digest_t null_digest = { 0 };
return (memcmp((const void*)null_digest, (const void*)digest, sizeof(digest_t)) ? FALSE : TRUE);
}
static inline void
brutus_digest_to_str(const digest_t digest,
digest_str_t digest_str)
{
int i;
memset((void*)digest_str, '\0', sizeof(digest_str_t));
if (brutus_digest_is_null(digest))
return;
for (i = 0; i < sizeof(digest_t); i++)
snprintf(&digest_str[2*i], 3, "%02x", (guint8)digest[i]);
}
void
brutus_get_digest_str(const char *str,
digest_str_t digest_str)
{
digest_t digest = { 0 };
md5_get_digest(str, strlen(str), digest);
brutus_digest_to_str(digest, digest_str);
}
gchar *
brutus_strip_trailing_and_leading_whitespace(const char *str)
{
gchar *retv = NULL;
int pos = 0;
if (!str)
return NULL;
// fast-forward to first non-space character
while (isspace(*str))
str++;
retv = g_strdup(str);
pos = strlen(str) - 1; // last character
while (0 <= pos) {
if (isspace(retv[pos]))
retv[pos] = '\0';
else
break;
pos--;
}
return retv;
}
gboolean
brutus_get_random_uuid(uuid_str_t uuid_str)
{
return (brutus_uuid(uuid_str) ? FALSE : TRUE);
}
void
brutus_free_lifeline(BRUTUS_BrutusProxy proxy,
PortableServer_POA poa,
struct BrutusCheckProxy *lifeline)
{
CORBA_boolean cb = CORBA_TRUE;
PortableServer_ObjectId *objid = NULL;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
cb = CORBA_Object_is_nil((CORBA_Object)lifeline->wrapper, ev);
if (!ORBIT2_EX(ev) && !cb) {
if (lifeline->key)
BRUTUS_BrutusProxy_killWrapper(proxy, lifeline->key, ev);
}
CORBA_Object_release((CORBA_Object)lifeline->wrapper, ev);
cb = CORBA_Object_is_nil((CORBA_Object)lifeline->filling, ev);
if (ORBIT2_EX(ev) || cb)
goto out;
objid = PortableServer_POA_reference_to_id (poa, (CORBA_Object)lifeline->filling, ev);
if (ORBIT2_EX(ev)) {
if (objid)
CORBA_free(objid);
goto out;
}
if (objid) {
PortableServer_POA_deactivate_object (poa, objid, ev);
CORBA_free(objid);
if (ORBIT2_EX(ev))
goto out;
}
CORBA_Object_release((CORBA_Object)lifeline->filling, ev);
out:
CORBA_exception_free(ev);
lifeline->key = 0;
lifeline->wrapper = CORBA_OBJECT_NIL;
lifeline->filling = CORBA_OBJECT_NIL;
}
void
brutus_base_class_free(BrutusBaseClass *base_class)
{
CORBA_boolean cb = CORBA_TRUE;
CORBA_Environment ev[1];
if (!base_class->connect_mutex)
return;
g_mutex_lock(base_class->connect_mutex);
CORBA_exception_init(ev);
if (brutus_is_connected(base_class->brutus_server,
base_class->mapi_session))
BRUTUS_IMAPISession_Destroy(base_class->mapi_session, base_class->instance_id, ev);
cb = CORBA_Object_is_nil(base_class->mapi_session, ev);
if (!ORBIT2_EX(ev) && !cb)
CORBA_Object_release(base_class->mapi_session, ev);
base_class->mapi_session = CORBA_OBJECT_NIL;
if (base_class->brutus_server)
g_free(base_class->brutus_server);
base_class->brutus_server = NULL;
if (base_class->exchange_server)
g_free(base_class->exchange_server);
base_class->exchange_server = NULL;
if (base_class->brutus_logon_corbaloc)
g_free(base_class->brutus_logon_corbaloc);
base_class->brutus_logon_corbaloc = NULL;
if (base_class->cache_dir)
g_free(base_class->cache_dir);
base_class->cache_dir = NULL;
if (base_class->mapi_profile)
CORBA_free(base_class->mapi_profile);
base_class->mapi_profile = NULL;
if (base_class->effective_mailbox)
CORBA_free(base_class->effective_mailbox);
base_class->effective_mailbox = NULL;
brutus_free_lifeline(base_class->brutus_proxy,
base_class->root_poa,
&base_class->lifeline);
cb = CORBA_Object_is_nil((CORBA_Object)base_class->brutus_proxy, ev);
if (!ORBIT2_EX(ev) && !cb) {
CORBA_Object_release((CORBA_Object)base_class->brutus_proxy, ev);
PRINT_IF_ORBIT2_EX(ev);
}
base_class->brutus_proxy = CORBA_OBJECT_NIL;
cb = CORBA_Object_is_nil((CORBA_Object)base_class->root_poa, ev);
if (!ORBIT2_EX(ev) && !cb) {
CORBA_Object_release((CORBA_Object)base_class->root_poa, ev);
PRINT_IF_ORBIT2_EX(ev);
}
base_class->root_poa = CORBA_OBJECT_NIL;
cb = CORBA_Object_is_nil((CORBA_Object)base_class->orb, ev);
if (!ORBIT2_EX(ev) && !cb) {
CORBA_Object_release((CORBA_Object)base_class->orb, ev);
PRINT_IF_ORBIT2_EX(ev);
}
base_class->orb = CORBA_OBJECT_NIL;
if (base_class->likely_connected_mutex)
g_mutex_free(base_class->likely_connected_mutex);
g_mutex_unlock(base_class->connect_mutex);
g_mutex_free(base_class->connect_mutex);
base_class->connect_mutex = NULL;
CORBA_exception_free(ev);
}
void
brutus_base_class_init(BrutusBaseClass *base_class)
{
base_class->orb = CORBA_OBJECT_NIL;
base_class->root_poa = CORBA_OBJECT_NIL;
base_class->mapi_session = CORBA_OBJECT_NIL;
base_class->brutus_proxy = CORBA_OBJECT_NIL;
base_class->expect_other_clients = TRUE;
base_class->likely_connected = FALSE;
base_class->likely_connected_mutex = g_mutex_new();
base_class->lifeline.key = 0;
base_class->lifeline.wrapper = CORBA_OBJECT_NIL;
base_class->lifeline.filling = CORBA_OBJECT_NIL;
base_class->instance_id = 0;
base_class->exchange_time_zone = 0;
base_class->client_time_zone = 0;
base_class->connect_mutex = g_mutex_new();
base_class->mapi_profile = NULL;
base_class->effective_mailbox = NULL;
base_class->brutus_logon_corbaloc = NULL;
base_class->cache_dir = NULL;
base_class->brutus_server = NULL;
base_class->exchange_server = NULL;
base_class->brutus_port = 0;
}
int
brutus_start_daemon(const enum E_BRUTUS_DAEMON which)
{
switch (which) {
case E_BRUTUS_SESSION_DAEMON :
return system("brutusd");
case E_BRUTUS_LOG_DAEMON :
return system("brutus-logd");
case E_BRUTUS_KEYRING_DAEMON :
return system("brutus-keyringd");
default:
g_assert_not_reached();
}
return -1;
}
pid_t
brutus_get_daemon_pid(const enum E_BRUTUS_DAEMON which)
{
int items = 0;
pid_t pid = -1;
gchar *path = NULL;
const gchar *pid_file_name = NULL;
FILE *pid_file = NULL;
switch (which) {
case E_BRUTUS_SESSION_DAEMON :
pid_file_name = BRUTUSD_PID_FILE_NAME;
break;
case E_BRUTUS_LOG_DAEMON :
pid_file_name = BRUTUS_LOGD_PID_FILE_NAME;
break;
case E_BRUTUS_KEYRING_DAEMON :
pid_file_name = BRUTUS_KEYRINGD_PID_FILE_NAME;
break;
default:
g_assert_not_reached();
}
path = g_strconcat(getenv("HOME"), "/", pid_file_name, NULL);
if (!path)
goto out;
pid_file = fopen(path, "r");
g_free(path);
if (!pid_file)
goto out;
items = fscanf(pid_file,"%d", &pid);
fclose(pid_file);
if (!items || (items > 1))
pid = -1;
out:
return pid;
}
/* sends SIGUSR2 to the specified daemon - no error if the daemon is dead or zombie */
void
brutus_restart_daemon(const enum E_BRUTUS_DAEMON which)
{
pid_t pid = brutus_get_daemon_pid(which);
if (0 < pid)
kill(pid, SIGUSR2);
}
/* sends SIGKILL to the specified daemon - no error if the daemon is dead or zombie */
void
brutus_kill_daemon(const enum E_BRUTUS_DAEMON which)
{
pid_t pid = brutus_get_daemon_pid(which);
if (0 < pid)
kill(pid, SIGKILL);
}
enum E_SOURCE_BRUTUS_TYPE
brutus_int_to_e_type(int i_rep)
{
switch (i_rep) {
case 1 :
return E_SOURCE_BRUTUS_CALENDAR;
case 2 :
return E_SOURCE_BRUTUS_TASKS;
case 3 :
return E_SOURCE_BRUTUS_NOTES;
case 4 :
return E_SOURCE_BRUTUS_ADDRESSBOOK_PAB;
case 5 :
return E_SOURCE_BRUTUS_ADDRESSBOOK_GAL;
default:
g_assert_not_reached();
}
return E_SOURCE_BRUTUS_UNKNOWN;
}
unsigned int
brutus_e_type_to_unsigned_int(enum E_SOURCE_BRUTUS_TYPE e_rep)
{
switch (e_rep) {
case E_SOURCE_BRUTUS_CALENDAR :
return 1;
case E_SOURCE_BRUTUS_TASKS :
return 2;
case E_SOURCE_BRUTUS_NOTES :
return 3;
case E_SOURCE_BRUTUS_ADDRESSBOOK_PAB :
return 4;
case E_SOURCE_BRUTUS_ADDRESSBOOK_GAL :
return 5;
default:
g_assert_not_reached();
}
return 0;
}
gchar*
brutus_mangle_uri(const gchar *uri)
{
int n;
gchar *mangled_uri = NULL;
if (!uri)
return NULL;
mangled_uri = g_strdup(uri);
for (n = 0; n < strlen(mangled_uri); n++) {
switch (mangled_uri[n]) {
case ':' :
case '/' :
mangled_uri[n] = '_';
}
}
return mangled_uri;
}
gboolean
brutus_is_likely_connected(BrutusBaseClass *base_class)
{
gboolean retv;
if (!g_mutex_trylock(base_class->likely_connected_mutex))
return FALSE;
retv = base_class->likely_connected;
g_mutex_unlock(base_class->likely_connected_mutex);
return retv;
}
struct st_likely_data {
BrutusBaseClass *base_class;
gboolean likely_connected;
};
static gpointer
set_likely_connected_thread_func(gpointer data)
{
struct st_likely_data *likely_data = (struct st_likely_data*)data;
g_mutex_lock(likely_data->base_class->likely_connected_mutex);
likely_data->base_class->likely_connected = likely_data->likely_connected;
g_mutex_unlock(likely_data->base_class->likely_connected_mutex);
return NULL;
}
void
brutus_set_likely_connected(BrutusBaseClass *base_class,
gboolean likely_connected)
{
GThread *thr = NULL;
struct st_likely_data likely_data = {
.base_class = base_class,
.likely_connected = likely_connected,
};
thr = g_thread_create(set_likely_connected_thread_func,
(gpointer)&likely_data,
TRUE,
NULL);
g_thread_join(thr);
}
time_t
brutus_get_server_utc_time(const char *brutus_server,
BRUTUS_IMAPISession mapi_session,
const char *exchange_server)
{
static gboolean timing_out = FALSE;
BRUTUS_TIME_OF_DAY_INFO exchange_tod;
char *tmp_exchange_server = NULL;
time_t utc_time = 0;
CORBA_boolean cb = CORBA_TRUE;
CORBA_Environment ev[1];
if (timing_out)
return 0;
if (!brutus_is_connected(brutus_server, mapi_session))
return 0;
if (!exchange_server)
return 0;
tmp_exchange_server = g_strjoin(NULL, "\\\\", exchange_server, NULL);
if (!tmp_exchange_server)
return 0;
CORBA_exception_init(ev);
cb = BRUTUS_IMAPISession_GetServerTime(mapi_session, tmp_exchange_server, &exchange_tod, ev);
g_free(tmp_exchange_server);
if (!ORBIT2_EX(ev) && cb)
utc_time = (time_t)exchange_tod.tod_elapsedt;
if (ORBIT2_EX(ev) && !strcmp(CORBA_exception_id(ev), ex_CORBA_TIMEOUT))
timing_out = TRUE;
CORBA_exception_free(ev);
return utc_time;
}
void
brutus_g_ptr_array_find_and_delete_string(GPtrArray *arr,
char *str)
{
guint n = 0;
for (n = 0; n < arr->len; n++) {
if (!strcmp(str, g_ptr_array_index(arr, n))) {
g_free(g_ptr_array_index(arr, n));
g_ptr_array_remove_index_fast(arr, n);
break;
}
}
}