"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "brutus-server/servant_impl/BrutusLogOnS_impl.cpp" of archive brutus-server-1.0.0.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  *    Brutus source file for the BrutusLogOn servant.
    3  *    Copyright (C) 2004 OMC Denmark ApS.
    4  *
    5  *    This program is free software; you can redistribute it and/or modify
    6  *    it under the terms of the GNU General Public License as published by
    7  *    the Free Software Foundation; either version 2 of the License, or
    8  *    (at your option) any later version.
    9  *
   10  *    This program is distributed in the hope that it will be useful,
   11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  *    GNU General Public License for more details.
   14  *
   15  *    You should have received a copy of the GNU General Public License
   16  *    along with this program; if not, write to the Free Software
   17  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   18  */
   19 
   20 #include <brutus-server/servant_impl/BrutusLogOnS_impl.h>
   21 #include <brutus-server/servant_impl/IMAPISessionS_impl.h>
   22 #include <tao/PortableServer/ServantActivatorC.h>
   23 #include <ace/string_base.h>
   24 
   25 #include <brutus-server/defines.h>
   26 #include <brutus-server/config.h>
   27 #include <brutus-server/macros.h>
   28 #include <brutus-server/rsa_utils.h>
   29 #include <Windows.h>
   30 #include <brutus-server/edkinc/edkmdb.h>
   31 
   32 #define MAPIGUID_H // do not include mapiguid.h
   33 #include <mapiutil.h>
   34 
   35 // MAPI_ALLOW_OTHERS is ignored due to security concerns
   36 // MAPI_NEW_SESSION is forced due to security concerns
   37 // All UI related flags are ignored
   38 // MAPI_FORCE_DOWNLOAD is ignored. Unclear how it should be interpreted
   39 static inline FLAGS native_logon_flags(const ::BRUTUS::BDEFINE Flags)
   40 {
   41 	::BRUTUS::BDEFINE flags = Flags;
   42 	FLAGS retval = 0;
   43 
   44 	retval |= MAPI_EXTENDED;
   45 	retval |= MAPI_NT_SERVICE;
   46 	retval |= MAPI_NEW_SESSION;
   47 
   48 	if (flags & ::BRUTUS::BRUTUS_UNIQUE_SESSION) // ignore this flag here
   49 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_UNIQUE_SESSION);
   50 
   51 	if (flags & ::BRUTUS::BRUTUS_MAPI_NO_MAIL) {
   52 		retval |= MAPI_NO_MAIL;
   53 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_NO_MAIL);
   54 	}
   55 	if (flags & ::BRUTUS::BRUTUS_MAPI_DEFAULT_SERVICES) {
   56 		retval |= MAPI_DEFAULT_SERVICES;
   57 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_DEFAULT_SERVICES);
   58 	}
   59 	if (flags & ::BRUTUS::BRUTUS_MAPI_TIMEOUT_SHORT) {
   60 		retval |= MAPI_TIMEOUT_SHORT;
   61 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_TIMEOUT_SHORT);
   62 	}
   63 	if (flags & ::BRUTUS::BRUTUS_MAPI_USE_DEFAULT) {
   64 		retval |= MAPI_USE_DEFAULT;
   65 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_USE_DEFAULT);
   66 	}
   67 	if (flags & ::BRUTUS::BRUTUS_MAPI_EXPLICIT_PROFILE) {
   68 		retval |= MAPI_EXPLICIT_PROFILE;
   69 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_EXPLICIT_PROFILE);
   70 	}
   71 	if (flags & ::BRUTUS::BRUTUS_MAPI_BG_SESSION) {
   72 		retval |= MAPI_BG_SESSION;
   73 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_BG_SESSION);
   74 	}
   75 
   76 	// Must(?) fix handling of Unicode characters
   77 	if (flags & ::BRUTUS::BRUTUS_MAPI_UNICODE) {
   78 		retval |= MAPI_UNICODE;
   79 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_UNICODE);
   80 	}
   81 
   82 	if (flags) {
   83 		char msg[128] = {0};
   84 		sprintf_s(msg, sizeof(msg), "Unknown or unsupported flag(s) from BRUTUS : %X", flags);
   85 		BRUTUS_LOG_BUG(msg);
   86 	}
   87 
   88 	return retval;
   89 }
   90 
   91 static inline FLAGS native_create_profile_flags(const ::BRUTUS::BDEFINE Flags)
   92 {
   93 	::BRUTUS::BDEFINE flags = Flags;
   94 	FLAGS retval = 0;
   95 
   96 	if (flags & ::BRUTUS::BRUTUS_MAPI_DEFAULT_SERVICES) {
   97 		retval |= MAPI_DEFAULT_SERVICES;
   98 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_DEFAULT_SERVICES);
   99 	}
  100 
  101 	// Must(?) fix handling of Unicode characters
  102 	if (flags & ::BRUTUS::BRUTUS_MAPI_UNICODE) {
  103 		retval |= MAPI_UNICODE;
  104 		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_MAPI_UNICODE);
  105 	}
  106 
  107 	if (flags) {
  108 		char msg[128] = {0};
  109 		sprintf_s(msg, sizeof(msg), "Unknown or unsupported flag(s) from BRUTUS : %X", flags);
  110 		BRUTUS_LOG_BUG(msg);
  111 	}
  112 
  113 	return retval;
  114 }
  115 
  116 static inline const char *spawn_status_msg(const ::BRUTUS::ProxyManager::SpawnStatus spawn_status)
  117 {
  118 	switch (spawn_status) {
  119 	case ::BRUTUS::ProxyManager::spawn_error_authentication :
  120 		return "Spawn failure: spawn_error_authentication";
  121 		break;
  122 	case ::BRUTUS::ProxyManager::spawn_error_mapi_logon :
  123 		return "Spawn failure: spawn_error_mapi_logon";
  124 		break;
  125 	case ::BRUTUS::ProxyManager::spawn_error_mapi_no_profile :
  126 		return "Spawn failure: spawn_error_mapi_no_profile";
  127 		break;
  128 	case ::BRUTUS::ProxyManager::spawn_error_lifeline :
  129 		return "Spawn failure: spawn_error_lifeline";
  130 		break;
  131 	case ::BRUTUS::ProxyManager::spawn_error_exception :
  132 		return "Spawn failure: spawn_error_exception";
  133 		break;
  134 	case ::BRUTUS::ProxyManager::spawn_error_impersonation :
  135 		return "Spawn failure: spawn_error_impersonation";
  136 		break;
  137 	case ::BRUTUS::ProxyManager::spawn_error_config :
  138 		return "Spawn failure: spawn_error_config";
  139 		break;
  140 	case ::BRUTUS::ProxyManager::spawn_error_corba :
  141 		return "Spawn failure: spawn_error_corba";
  142 		break;
  143 	case ::BRUTUS::ProxyManager::spawn_error_mapi_init :
  144 		return "Spawn failure: spawn_error_mapi_init";
  145 		break;
  146 	case ::BRUTUS::ProxyManager::spawn_error_spawn :
  147 		return "Spawn failure: spawn_error_spawn";
  148 		break;
  149 	case ::BRUTUS::ProxyManager::spawn_duplicate :
  150 		return "Spawn failure: spawn_duplicate";
  151 		break;
  152 	case ::BRUTUS::ProxyManager::spawn_ok :
  153 		return "Spawn OK";
  154 		break;
  155 	default :
  156 		return "Unknown Spawn failure";
  157 		break;
  158 	}
  159 }
  160 
  161 static inline bool authenticate_user(const char *WindowsUserName,
  162 				     const char *WindowsDomainName,
  163 				     const char *WindowsUserPassword)
  164 {
  165 	BRUTUS_LOG_REF;
  166 	HANDLE credentials = NULL;
  167 
  168 	if (LogonUser((char*)WindowsUserName,
  169 		      (char*)WindowsDomainName,
  170 		      (char*)WindowsUserPassword,
  171 		      LOGON32_LOGON_NETWORK,
  172 		      LOGON32_PROVIDER_DEFAULT,
  173 		      &credentials)) {
  174 		CloseHandle(credentials);
  175 		return true;
  176 	}
  177 	if (credentials)
  178 		CloseHandle(credentials);
  179 
  180 	DWORD err = GetLastError();
  181 	char msg[512] = {0};
  182 	LPVOID msg_buf;
  183 
  184 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  185 		      NULL,
  186 		      err,
  187 		      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  188 		      (LPTSTR) &msg_buf,
  189 		      0,
  190 		      NULL );
  191 	((char*)msg_buf)[strlen((char*)msg_buf) - 2] = '\0';
  192 
  193 	_snprintf_s(msg, sizeof(msg), sizeof(msg), "LogonUser(%s\\%s) failed - GetLastError() returned: 0x%X (%s)", WindowsDomainName, WindowsUserName, err, (const char*)msg_buf);
  194 	LocalFree(msg_buf);
  195 	BRUTUS_LOG_SUB_PRIVATE(msg);
  196 
  197 	return false;
  198 }
  199 
  200 BRUTUS_BrutusLogOn_i::BRUTUS_BrutusLogOn_i(::PortableServer::POA_ptr Poa,
  201 					   ::SessionRegistry *Registry,
  202 					   const bool ProcessPerSession,
  203 					   const bool OnlyAdministrator,
  204 					   const bool Authenticate,
  205 					   const bool ProfilesOnDisk,
  206 					   const unsigned long CheckLifeDelay,
  207 					   ::CORBA::ORB_ptr ORB)
  208 	: poa_(::PortableServer::POA::_duplicate(Poa)),
  209 	  served_sessions_(Registry),
  210 	  process_per_session_(ProcessPerSession),
  211 	  only_administrator_(OnlyAdministrator),
  212 	  authenticate_(Authenticate),
  213 	  profiles_on_disk_(ProfilesOnDisk),
  214 	  exchange_2007_(false),
  215 	  check_life_delay_(CheckLifeDelay)
  216 {
  217 	Config *conf = new Config();
  218 
  219 	// load configuration
  220 	if (conf->load(BRUTUS_CONF)) {
  221 		delete conf;
  222 		throw 0;
  223 	}
  224 
  225 	// MAPI options
  226 	char *exchange_version_str = NULL;
  227 	exchange_version_str = conf->get_value("EXCHANGE_SERVER_VERSION");
  228 	if ((exchange_version_str) && (!strcmp(exchange_version_str, "2007")))
  229 		exchange_2007_ = true;
  230 	free(exchange_version_str);
  231 	delete conf;
  232 
  233 	internal_orb_ = ::CORBA::ORB::_duplicate(ORB);
  234 	proxy_manager_ = ::BRUTUS::ProxyManager::_nil();
  235 	if (process_per_session_) {
  236 		try {
  237 			::CORBA::Object_var object = internal_orb_->string_to_object(PROXY_MANAGER_IOR);
  238 			proxy_manager_ = ::BRUTUS::ProxyManager::_narrow(object.in());
  239 		}
  240 		catch (...) {
  241 		}
  242 	}
  243 }
  244 
  245 void BRUTUS_BrutusLogOn_i::GetVersion(::BRUTUS::BrutusLogOn::BrutusVersion_out version)
  246 {
  247 	BRUTUS_LOG_REF;
  248 	BRUTUS_LOG_SUB_INF("Entering BRUTUS_BrutusLogOn_i::GetVersion()");
  249 
  250 	::BRUTUS::BrutusLogOn::BrutusVersion_var ver;
  251 
  252 	try {
  253 		ver = new ::BRUTUS::BrutusLogOn::BrutusVersion;
  254 	}
  255 	catch (std::bad_alloc &) {
  256 		BRUTUS_LOG_SUB_ERR("No memory");
  257 		throw ::CORBA::NO_MEMORY();
  258 	}
  259 	ver->major = (::CORBA::UShort)BRUTUS_VERSION_MAJOR;
  260 	ver->minor = (::CORBA::UShort)BRUTUS_VERSION_MINOR;
  261 	ver->micro = (::CORBA::UShort)BRUTUS_VERSION_MICRO;
  262 	ver->release_tag = (::CORBA::UShort)BRUTUS_VERSION_RELEASE_TAG;
  263 
  264 	version = ver._retn();
  265 
  266 	BRUTUS_LOG_SUB_INF("Leaving BRUTUS_BrutusLogOn_i::GetVersion()");
  267 }
  268 
  269 void BRUTUS_BrutusLogOn_i::GetPublicKey(::BRUTUS::seq_octet_out PubKey)
  270 {
  271 	BRUTUS_LOG_REF;
  272 	BRUTUS_LOG_SUB_INF("Entering BRUTUS_BrutusLogOn_i::GetPublicKey()");
  273 
  274 	char *key = NULL;
  275 	int len = 0;
  276 	struct _stat pk_stat = { 0 };
  277 
  278 	::BRUTUS::seq_octet_var pubkey;
  279 	try {
  280 		pubkey = new ::BRUTUS::seq_octet;
  281 	}
  282 	catch (std::bad_alloc &) {
  283 		BRUTUS_LOG_SUB_ERR("No memory");
  284 		throw ::CORBA::NO_MEMORY();
  285 	}
  286 	pubkey->length(0);
  287 
  288 	// get size of public key
  289 	if (_stat(PUBLIC_KEY, &pk_stat)) {
  290 		BRUTUS_LOG_SUB_ERR("Could not stat public key file");
  291 		goto exit;
  292 	}
  293 	key = (char*)malloc(pk_stat.st_size);
  294 	if (!key) {
  295 		BRUTUS_LOG_SUB_ERR("No memory");
  296 		throw ::CORBA::NO_MEMORY();
  297 	}
  298 
  299 	FILE *file = NULL;
  300 	if (fopen_s(&file, PUBLIC_KEY, "r")) {
  301 		BRUTUS_LOG_SUB_ERR("Could not open public key file");
  302 		goto exit;
  303 	}
  304 
  305 	len = fscanf_s(file, "%as", &key, pk_stat.st_size);
  306 	if (file) // C6387
  307 		fclose(file);
  308 	if (!len)
  309 		BRUTUS_LOG_SUB_ERR("Could not read public key");
  310 	else {
  311 		unsigned long n = 0;
  312 		pubkey->length(len);
  313 		do {
  314 			pubkey[n] = (::CORBA::Octet)key[n];
  315 			n++;
  316 		} while(--len);
  317 	}
  318 
  319 exit:
  320 	free(key);
  321 	PubKey = pubkey._retn();
  322 
  323 	BRUTUS_LOG_SUB_INF("Leaving BRUTUS_BrutusLogOn_i::GetPublicKey()");
  324 }
  325 
  326 ::BRUTUS::BRESULT BRUTUS_BrutusLogOn_i::Logon(::BRUTUS::BrutusCheck_ptr LifeLine,
  327 					      const char *MAPIProfileName,
  328 					      const char *MAPIProfilePassword,
  329 					      const char *WindowsUserName,
  330 					      const char *WindowsDomainName,
  331 					      const char *WindowsUserPassword,
  332 					      const char *MailboxName,
  333 					      const char *ServerName,
  334 					      ::BRUTUS::BDEFINE LogonFlags,
  335 					      ::BRUTUS::BDEFINE ProfileFlags,
  336 					      ::BRUTUS::SERVER_TYPE ServerType,
  337 					      ::CORBA::ULong_out InstanceID,
  338 					      ::BRUTUS::IMAPISession_out Session)
  339 {
  340 	BRUTUS_LOG_REF;
  341 	Session = ::BRUTUS::IMAPISession::_nil();
  342 
  343 	if (::CORBA::is_nil(LifeLine)) {
  344 		BRUTUS_LOG_SUB_BUG("LifeLine parameter was NIL");
  345 		return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
  346 	}
  347 
  348 	try {
  349 		::CORBA::String_var life_line_ior = internal_orb_->object_to_string(LifeLine);
  350 		if (NULL == life_line_ior.in()) {
  351 			BRUTUS_LOG_SUB_BUG("IOR is NULL");
  352 			return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
  353 		}
  354 		BRUTUS_LOG_SUB_INF("Validating LifeLine object reference");
  355 		BRUTUS_LOG_SUB_INF(life_line_ior.in());
  356 		LifeLine->ping();
  357 	}
  358 	catch (const ::CORBA::TIMEOUT &) {
  359 		BRUTUS_LOG_SUB_BUG("Timeout trying to validate lifeline");
  360 		return ::BRUTUS::BRUTUS_LIFELINE_TIMEOUT;
  361 	}
  362 	catch (const ::CORBA::Exception &e) {
  363 		BRUTUS_LOG_SUB_BUG(e._info().c_str());
  364 		return ::BRUTUS::BRUTUS_EXCEPTION_FROM_CLIENT;
  365 	}
  366 	catch (...) {
  367 		BRUTUS_LOG_SUB_BUG("Unknown exception caught");
  368 		return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  369 	}
  370 
  371 	return create_session(check_life_delay_,
  372 			      LifeLine,
  373 			      MAPIProfileName,
  374 			      MAPIProfilePassword,
  375 			      WindowsUserName,
  376 			      (const char*)(strlen(WindowsDomainName) ? WindowsDomainName : NULL), // take care of UPN authentication
  377 			      WindowsUserPassword,
  378 			      MailboxName,
  379 			      ServerName,
  380 			      LogonFlags,
  381 			      ProfileFlags,
  382 			      ServerType,
  383 			      InstanceID,
  384 			      Session);
  385 }
  386 
  387 ::BRUTUS::BRESULT BRUTUS_BrutusLogOn_i::create_session(const unsigned long CheckLifeDelay,
  388 						       ::BRUTUS::BrutusCheck_ptr LifeLine,
  389 						       const char *MAPIProfileName,
  390 						       const char *MAPIProfilePassword,
  391 						       const char *WindowsUserName,
  392 						       const char *WindowsDomainName,
  393 						       const char *WindowsUserPassword,
  394 						       const char *MailboxName,
  395 						       const char *ServerName,
  396 						       ::BRUTUS::BDEFINE LogonFlags,
  397 						       ::BRUTUS::BDEFINE ProfileFlags,
  398 						       ::BRUTUS::SERVER_TYPE ServerType,
  399 						       ::CORBA::ULong_out InstanceID,
  400 						       ::BRUTUS::IMAPISession_out Session)
  401 {
  402 	BRUTUS_LOG_REF;
  403 	BRUTUS_LOG_SUB_INF("Entering BRUTUS_BrutusLogOn_i::Logon()");
  404 
  405 	bool null_profile_passwd = false;
  406 	bool retry = true;
  407 	::BRUTUS::IMAPISession_var session = ::BRUTUS::IMAPISession::_nil();
  408 	::BRUTUS::BRESULT br = ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  409 	const char *user = only_administrator_ ? "Administrator" : WindowsUserName;
  410 
  411 	InstanceID = 0;
  412 	Session = ::BRUTUS::IMAPISession::_nil();
  413 
  414 	if (authenticate_) {
  415 		if (!authenticate_user(user, WindowsDomainName, WindowsUserPassword))
  416 			return ::BRUTUS::BRUTUS_MAPI_E_LOGON_FAILED;
  417 		else {
  418 			char msg[512] = {0};
  419 			sprintf_s(msg, sizeof(msg), "%s\\%s authenticated sucessfully - proceeding with logon", WindowsDomainName, user);
  420 			BRUTUS_LOG_SUB_PRIVATE(msg);
  421 		}
  422 	}
  423 	if (!MAPIProfileName || !strlen(MAPIProfileName))
  424 		return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
  425 	else if (strlen(MAPIProfileName) > 64)
  426 		return ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG;
  427 	if (MAPIProfilePassword && (strlen(MAPIProfilePassword) > 64))
  428 		return ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG;
  429 	if (!strlen(MAPIProfilePassword))
  430 		null_profile_passwd = true;
  431 
  432 	BRUTUS_LOG_SUB_PRIVATE(MAPIProfileName);
  433 
  434 	if (process_per_session_) {
  435 		::CORBA::Object_var object = ::CORBA::Object::_nil();
  436 		const char *server_type = NULL;
  437 
  438 		switch (ServerType) {
  439 		case ::BRUTUS::SERVER_TYPE_EXCHANGE:
  440 			server_type = "MSEMS";
  441 			break;
  442 		case ::BRUTUS::SERVER_TYPE_DOMINO:
  443 			server_type = "NOTES";
  444 			break;
  445 		default:
  446 			BRUTUS_LOG_SUB_BUG("Message service not supported");
  447 			return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
  448 		}
  449 
  450 		if (::CORBA::is_nil(proxy_manager_.in())) {
  451 			try {
  452 				object = internal_orb_->string_to_object(PROXY_MANAGER_IOR);
  453 				proxy_manager_ = ::BRUTUS::ProxyManager::_narrow(object.in());
  454 			}
  455 			catch (...) {
  456 			}
  457 		}
  458 		if (::CORBA::is_nil(proxy_manager_.in())) {
  459 			BRUTUS_LOG_SUB_CRITICAL("Could not get Proxy Manager reference");
  460 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  461 		}
  462 
  463 		try {
  464 			::CORBA::String_var life_line_ior = internal_orb_->object_to_string(LifeLine);
  465 			if (NULL == life_line_ior.in()) {
  466 				BRUTUS_LOG_SUB_BUG("IOR is NULL");
  467 				return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  468 			}
  469 
  470 			if (!proxy_manager_->setUser(life_line_ior.in(),
  471 						     user,
  472 						     WindowsDomainName,
  473 						     WindowsUserPassword,
  474 						     MAPIProfileName,
  475 						     MAPIProfilePassword,
  476 						     MailboxName,
  477 						     ServerName,
  478 						     server_type,
  479 						     LogonFlags,
  480 						     ProfileFlags)) {
  481 				char msg[512] = {0};
  482 				sprintf_s(msg, sizeof(msg), "Could not spawn proxy process for %s/%s. Impersonation failed, check user privileges.", user, WindowsDomainName);
  483 				ACE_DEBUG((LM_CRITICAL, ACE_TEXT(msg)));
  484 				BRUTUS_LOG_SUB_CRITICAL(msg);
  485 				return ::BRUTUS::BRUTUS_MAPI_E_LOGON_FAILED;
  486 			}
  487 		}
  488 		catch (...) {
  489 			BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  490 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  491 		}
  492 
  493 		::CORBA::String_var session_ior = (const char*)"";
  494 		::BRUTUS::ProxyManager::SpawnStatus spawn_status;
  495 		try { // this call takes the longest time in the logon process
  496 			spawn_status = proxy_manager_->getSession(MAPIProfileName,
  497 								  session_ior.out());
  498 		}
  499 		catch (const ::CORBA::Exception &e) {
  500 			BRUTUS_LOG_SUB_CRITICAL(e._info().c_str());
  501 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  502 		}
  503 		catch (...) {
  504 			BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  505 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  506 		}
  507 		if ((spawn_status == ::BRUTUS::ProxyManager::spawn_ok) || (spawn_status == ::BRUTUS::ProxyManager::spawn_duplicate)) {
  508 			try {
  509 				object = internal_orb_->string_to_object(session_ior.in());
  510 				session = ::BRUTUS::IMAPISession::_narrow(object.in());
  511 			}
  512 			catch (...) {
  513 				return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  514 			}
  515 			if (::CORBA::is_nil(object.in()))
  516 				return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  517 		} else {
  518 			switch (spawn_status) {
  519 			case ::BRUTUS::ProxyManager::spawn_error_authentication :
  520 			case ::BRUTUS::ProxyManager::spawn_error_mapi_logon :
  521 				br = ::BRUTUS::BRUTUS_MAPI_E_LOGON_FAILED;
  522 				break;
  523 			case ::BRUTUS::ProxyManager::spawn_error_mapi_no_profile :
  524 				br = ::BRUTUS::BRUTUS_MAPI_E_NOT_FOUND;
  525 				break;
  526 			case ::BRUTUS::ProxyManager::spawn_error_lifeline :
  527 				br = ::BRUTUS::BRUTUS_LIFELINE_ERROR;
  528 				break;
  529 			case ::BRUTUS::ProxyManager::spawn_error_exception :
  530 			case ::BRUTUS::ProxyManager::spawn_error_impersonation :
  531 			case ::BRUTUS::ProxyManager::spawn_error_config :
  532 			case ::BRUTUS::ProxyManager::spawn_error_corba :
  533 			case ::BRUTUS::ProxyManager::spawn_error_mapi_init :
  534 			case ::BRUTUS::ProxyManager::spawn_error_spawn :
  535 			default :
  536 				br = ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  537 			}
  538 			BRUTUS_LOG_SUB_CRITICAL(spawn_status_msg(spawn_status));
  539 			return br;
  540 		}
  541 
  542 		// the user is already authenticated
  543 		if (spawn_status == ::BRUTUS::ProxyManager::spawn_duplicate) {
  544 			BRUTUS_LOG_SUB_INF("Duplicate session created");
  545 			InstanceID = session->addLifeline(LifeLine);
  546 		} else {
  547 			BRUTUS_LOG_SUB_INF("New session created");
  548 			InstanceID = 0;
  549 		}
  550 
  551 		br = ::BRUTUS::BRUTUS_S_OK;
  552 		Session = session._retn();
  553 	} else {
  554 		LPMAPISESSION mapi_session = NULL;
  555 		FLAGS flags = native_logon_flags(LogonFlags);
  556 
  557 		HRESULT hr = E_FAIL;
  558 
  559 	create_mapi_session:
  560 		hr = MAPILogonEx(0,
  561 				 (char*)MAPIProfileName,
  562 				 (char*)(null_profile_passwd ? NULL : MAPIProfilePassword),
  563 				 flags,
  564 				 &mapi_session);
  565 		if (retry) {
  566 			if ((!profiles_on_disk_ && (MAPI_E_LOGON_FAILED == hr))
  567 			    || (profiles_on_disk_ && (MAPI_E_NOT_FOUND == hr))) {
  568 				br = CreateProfile(MAPIProfileName,
  569 						   MAPIProfilePassword,
  570 						   MailboxName,
  571 						   ServerName,
  572 						   ServerType,
  573 						   ProfileFlags,
  574 						   (exchange_2007_ ? true : false));
  575 				if (::BRUTUS::BRUTUS_S_OK != br) {
  576 					BRUTUS_LOG_SUB_CRITICAL("Could not create MAPI Profile - Incorrect user credentials or insufficient privileges");
  577 					return br;
  578 				}
  579 				retry = false;
  580 				goto create_mapi_session;
  581 			}
  582 		}
  583 		if (!hresult_to_bresult(hr, br)) {
  584 			if (mapi_session) {
  585 				BRUTUS_LOG_SUB_ERR("MAPI session is non-NIL but MAPILogonEx failed.");
  586 				try {
  587 					mapi_session->Release();
  588 				}
  589 				catch (...) {
  590 					BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  591 				}
  592 			}
  593 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  594 		}
  595 		if (S_OK != hr) {
  596 			if (mapi_session) {
  597 				BRUTUS_LOG_SUB_ERR("MAPI session is non-NIL but MAPILogonEx failed.");
  598 				try {
  599 					mapi_session->Release();
  600 				}
  601 				catch (...) {
  602 					BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  603 				}
  604 			}
  605 			{
  606 				char msg[128] = {0};
  607 				const char *reason;
  608 
  609 				if (MAPI_E_TIMEOUT == hr)
  610 					reason = "MAPI_E_TIMEOUT";
  611 				else
  612 					reason = "MAPI_E_LOGON_FAILED";
  613 
  614 				sprintf_s(msg, sizeof(msg), "MAPILogonEx(%s) failed - %s", MAPIProfileName, reason);
  615 				BRUTUS_LOG_SUB_PRIVATE(msg);
  616 			}
  617 			return br;
  618 		}
  619 
  620 		// create the child poa for this mapi session
  621 		::PortableServer::POA_var session_poa = ::PortableServer::POA::_nil();
  622 	again:
  623 		try {
  624 			session_poa = create_poa(MAPIProfileName,
  625 						 ::PortableServer::POAManager::_nil(),
  626 						 poa_.in());
  627 		}
  628 		catch (::PortableServer::POA::AdapterAlreadyExists &) {
  629 			BRUTUS_LOG_ERR("POA exists - terminating former instance, replacing with new...");
  630 			served_sessions_->sign_out(MAPIProfileName, 1);
  631 			goto again;
  632 		}
  633 		if (::CORBA::is_nil(session_poa)) {
  634 			BRUTUS_LOG_SUB_ERR("Could not create session POA");
  635 			try {
  636 				mapi_session->Release();
  637 			}
  638 			catch (...) {
  639 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  640 			}
  641 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  642 		}
  643 
  644 		// activate the IMAPISession object's poa so that requests can be served
  645 		::PortableServer::POAManager_var poa_manager = session_poa->the_POAManager();
  646 		try {
  647 			poa_manager->activate();
  648 		}
  649 		catch (::PortableServer::POAManager::AdapterInactive &) {
  650 			BRUTUS_LOG_SUB_CRITICAL("POAManager::activate() throwed an exception");
  651 			try {
  652 				mapi_session->Release();
  653 			}
  654 			catch (...) {
  655 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  656 			}
  657 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  658 		}
  659 
  660 		// the session poa is now created so add it to the session registry
  661 		unsigned long id = served_sessions_->add_entry(session_poa.in(),
  662 							       MAPIProfileName);
  663 		if (!id) {
  664 			BRUTUS_LOG_SUB_ERR("Could not add entry into managed sessions");
  665 
  666 			session_poa->destroy(1, 0);
  667 			try {
  668 				mapi_session->Release();
  669 			}
  670 			catch (...) {
  671 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  672 			}
  673 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  674 		}
  675 
  676 		// create the IMAPISession servant
  677 		BRUTUS_IMAPISession_i *mapi_session_servant;
  678 		try {
  679 			mapi_session_servant = new BRUTUS_IMAPISession_i(mapi_session,
  680 									 session_poa.in(),
  681 									 served_sessions_,
  682 									 id,
  683 									 internal_orb_.in(),
  684 									 LifeLine,
  685 									 CheckLifeDelay,
  686 									 false);
  687 		}
  688 		catch (std::bad_alloc &) {
  689 			BRUTUS_LOG_SUB_ERR("No memory");
  690 
  691 			served_sessions_->sign_out(id, 0);
  692 			try {
  693 				mapi_session->Release();
  694 			}
  695 			catch (...) {
  696 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  697 			}
  698 			return ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_MEMORY;
  699 		}
  700 
  701 		// create the IMAPISession object and register it in the session poa
  702 		::PortableServer::ObjectId_var oid;
  703 		try {
  704 			::PortableServer::ServantBase_var owner_transfer(mapi_session_servant);
  705 			oid = session_poa->activate_object(mapi_session_servant);
  706 		}
  707 		catch (const ::PortableServer::POA::WrongPolicy &) {
  708 			BRUTUS_LOG_SUB_CRITICAL("::PortableServer::POA::WrongPolicy exception caught");
  709 			served_sessions_->sign_out(id, 0);
  710 			try {
  711 				mapi_session->Release();
  712 			}
  713 			catch (...) {
  714 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  715 			}
  716 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  717 		}
  718 		catch (const ::PortableServer::POA::ServantAlreadyActive &) {
  719 			BRUTUS_LOG_SUB_CRITICAL("::PortableServer::POA::ServantAlreadyActive exception caught");
  720 			served_sessions_->sign_out(id, 0);
  721 			try {
  722 				mapi_session->Release();
  723 			}
  724 			catch (...) {
  725 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  726 			}
  727 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  728 		}
  729 
  730 		// get the object reference
  731 		::CORBA::Object_var obj = ::CORBA::Object::_nil();
  732 		try {
  733 			obj = session_poa->id_to_reference(oid.in());
  734 		}
  735 		catch (const ::PortableServer::POA::WrongPolicy &) {
  736 			BRUTUS_LOG_SUB_CRITICAL("::PortableServer::POA::WrongPolicy exception caught");
  737 		}
  738 		catch (const ::PortableServer::POA::ObjectNotActive &) {
  739 			BRUTUS_LOG_SUB_CRITICAL("::PortableServer::POA::ObjectNotActive exception caught");
  740 		}
  741 		if (::CORBA::is_nil(obj)) {
  742 			BRUTUS_LOG_SUB_CRITICAL("::PortableServer::POA::id_to_reference() returned NIL");
  743 			served_sessions_->sign_out(id, 0);
  744 			try {
  745 				mapi_session->Release();
  746 			}
  747 			catch (...) {
  748 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  749 			}
  750 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  751 		}
  752 		session = ::BRUTUS::IMAPISession::_narrow(obj);
  753 		if (::CORBA::is_nil(session)) {
  754 			BRUTUS_LOG_SUB_CRITICAL("::BRUTUS::IMAPISession::_narrow() returned NIL");
  755 			served_sessions_->sign_out(id, 0);
  756 			try {
  757 				mapi_session->Release();
  758 			}
  759 			catch (...) {
  760 				BRUTUS_LOG_SUB_CRITICAL("Exception caught");
  761 			}
  762 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  763 		}
  764 		Session = session._retn();
  765 
  766 		{
  767 			char msg[128] = {0};
  768 			sprintf_s(msg, sizeof(msg), "%s has logged on", MAPIProfileName);
  769 			BRUTUS_LOG_SUB_PRIVATE(msg);
  770 		}
  771 		br = ::BRUTUS::BRUTUS_S_OK;
  772 	}
  773 	BRUTUS_LOG_SUB_PRIVATE(MAPIProfileName);
  774 
  775 	BRUTUS_LOG_SUB_INF("Leaving BRUTUS_BrutusLogOn_i::Logon()");
  776 
  777 	return br;
  778 }
  779 
  780 ::BRUTUS::BRESULT BRUTUS_BrutusLogOn_i::CreateProfile(const char *MAPIProfileName,
  781 						      const char *MAPIProfilePassword,
  782 						      const char *MailboxName,
  783 						      const char *ServerName,
  784 						      ::BRUTUS::SERVER_TYPE ServerType,
  785 						      ::BRUTUS::BDEFINE ProfileFlags,
  786 						      ::CORBA::Boolean ConnectIgnoreNoPF)
  787 {
  788 	BRUTUS_LOG_REF;
  789 	BRUTUS_LOG_SUB_INF("Entering BRUTUS_BrutusLogOn_i::CreateProfile()");
  790 
  791 	if (!MAPIProfileName)
  792 		return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
  793 	else if (strlen(MAPIProfileName) > 64)
  794 		return ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG;
  795 	if (MAPIProfilePassword && (strlen(MAPIProfilePassword) > 64))
  796 		return ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG;
  797 	if (!strlen(MAPIProfilePassword))
  798 		MAPIProfilePassword = NULL;
  799 
  800 	BRUTUS_LOG_SUB_PRIVATE(MAPIProfileName);
  801 	BRUTUS_LOG_SUB_PRIVATE(MailboxName);
  802 	BRUTUS_LOG_SUB_PRIVATE(ServerName);
  803 
  804 	const char *server_type = NULL;
  805 	const char *service_display_name = NULL;
  806 	LPPROFSECT lpProfSect = NULL;
  807 	LPPROFADMIN lpProfAdmin = NULL;
  808 	LPSERVICEADMIN lpSvcAdmin = NULL;
  809 	LPMAPITABLE lpMsgSvcTable = NULL;
  810 	SRestriction sres;
  811 	SPropValue SvcProps;
  812 	LPSRowSet lpSvcRows = NULL; // Rowset to hold results of table query.
  813 	SPropValue rgval[2]; // Property structure to hold values we want to set.
  814 	::BRUTUS::BRESULT br = ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  815 	HRESULT hr = S_OK;
  816 
  817 	// I am not entirely clear on this. I don't feel good about initializing MAPI
  818 	// several times in the same thread and this method is a one-time call anyway
  819 	// so I better just serialize it with a RW mutex.
  820 	ACE_Write_Guard<ACE_RW_Mutex> guard(mutex_);
  821 
  822 	if (process_per_session_) {
  823 		MAPIINIT_0 mapi_init;
  824 
  825 		mapi_init.ulFlags = MAPI_MULTITHREAD_NOTIFICATIONS | MAPI_NT_SERVICE | (profiles_on_disk_ ? MAPI_TEMPORARY_PROFILES : 0);
  826 		mapi_init.ulVersion = MAPI_INIT_VERSION;
  827 		hr = MAPIInitialize(&mapi_init);
  828 		if (hr != S_OK) {
  829 			BRUTUS_LOG_SUB_CRITICAL("Could not initialize MAPI");
  830 			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
  831 		}
  832 		BRUTUS_LOG_SUB_INF("MAPI is initialized");
  833 
  834 	}
  835 
  836 	FLAGS flags = native_create_profile_flags(ProfileFlags);
  837 
  838 	// This indicates columns we want returned from HrQueryAllRows.
  839 	SizedSPropTagArray(2, sptCols) = { 2, PR_SERVICE_NAME, PR_SERVICE_UID };
  840 
  841 	// Get an IProfAdmin interface.
  842 	hr = MAPIAdminProfiles(0, &lpProfAdmin);
  843 	if (hr != S_OK) {
  844 		BRUTUS_LOG_SUB_BUG("MAPIAdminProfiles() failed");
  845 		goto out;
  846 	}
  847 
  848 	// Create a new profile.
  849 	hr = lpProfAdmin->CreateProfile((char*)MAPIProfileName,
  850 					(char*)MAPIProfilePassword,
  851 					NULL,
  852 					flags);
  853 	if (hr != S_OK) {
  854 		char __msg[128] = { 0 };
  855 		sprintf_s(__msg, sizeof(__msg), "Could not create profile, HRESULT = %#.8lx (", hr);
  856 		strcat_s(__msg, sizeof(__msg) - strlen(__msg), hresult_to_str(hr));
  857 		strcat_s(__msg, sizeof(__msg) - strlen(__msg), ")");
  858 		BRUTUS_LOG_SUB_BUG(__msg);
  859 		goto out;
  860 	}
  861 
  862 	// Get an IMsgServiceAdmin interface off of the IProfAdmin interface.
  863 	hr = lpProfAdmin->AdminServices((char*)MAPIProfileName,
  864 					(char*)MAPIProfilePassword,
  865 					NULL,
  866 					flags,
  867 					&lpSvcAdmin);
  868 	if (hr != S_OK) {
  869 		BRUTUS_LOG_SUB_BUG("Could not get IMsgServiceAdmin interface");
  870 		goto out;
  871 	}
  872