Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
my
$VERSION
=
"0.026"
;
my
$DEBUG
= 1;
my
$ADS_SID_HEXSTRING
= 0x01;
my
$ADS_SID_WINNT_PATH
= 0x05;
my
$ADS_RIGHT_EXCH_MODIFY_USER_ATT
= 0x02;
my
$ADS_RIGHT_EXCH_MAIL_SEND_AS
= 0x08;
my
$ADS_RIGHT_EXCH_MAIL_RECEIVE_AS
= 0x10;
my
$ADS_ACETYPE_ACCESS_ALLOWED
= 0x00;
my
$ADS_SECURE_AUTHENTICATION
= 0x1;
my
$ADS_USE_ENCRYPTION
= 0x2;
my
$ADS_USE_SSL
= 0x2;
my
$ADS_READONLY_SERVER
= 0x4;
my
$ADS_PROMPT_CREDENTIALS
= 0x8;
my
$ADS_NO_AUTHENTICATION
= 0x10;
my
$ADS_FAST_BIND
= 0x20;
my
$ADS_USE_SIGNING
= 0x40;
my
$ADS_USE_SEALING
= 0x80;
my
$ADS_USE_DELEGATION
= 0x100;
my
$ADS_SERVER_BIND
= 0x200;
my
$ADS_RIGHT_DS_CREATE_CHILD
= 0x1;
my
$ADS_ACEFLAG_INHERIT_ACE
= 0x2;
sub
new {
my
$server
;
my
$ver
=
""
;
if
(
scalar
(
@_
) == 1) {
if
(
$_
[0] eq
"5.5"
||
$_
[0] eq
"6.0"
) {
$ver
=
$_
[0];
}
else
{
$server
=
$_
[0];
}
}
elsif
(
scalar
(
@_
) == 2) {
if
(
$_
[0] eq
"Win32::Exchange"
) {
if
(
$_
[1] eq
"5.5"
||
$_
[1] eq
"6.0"
) {
$ver
=
$_
[1];
}
else
{
$server
=
$_
[1];
}
}
else
{
_ReportArgError(
"new"
,
scalar
(
@_
));
}
}
else
{
_ReportArgError(
"new"
,
scalar
(
@_
));
return
0;
}
my
$class
=
"Win32::Exchange"
;
my
$ldap_provider
= {};
if
(
$ver
eq
""
) {
my
%version
;
if
(!Win32::Exchange::GetVersion(
$server
,\
%version
)) {
return
undef
;
}
else
{
$ver
=
$version
{
'ver'
}
}
}
elsif
(
$ver
eq
"5.5"
) {
if
(
$ldap_provider
= Win32::OLE->new(
'ADsNamespaces'
)) {
return
bless
$ldap_provider
,
$class
;
}
else
{
_DebugComment(
"Failed creating ADsNamespaces object"
);
return
undef
;
}
}
elsif
(
$ver
eq
"6.0"
) {
if
(
$ldap_provider
= Win32::OLE->new(
'CDO.Person'
)) {
return
bless
$ldap_provider
,
$class
;
}
else
{
_DebugComment(
"Failed creating CDO.Person object\n"
);
return
undef
;
}
}
else
{
_DebugComment(
"Unable to verify version information for version: $ver\n"
);
return
undef
;
}
}
sub
DESTROY {
my
$object
=
shift
;
bless
$object
,
"Win32::OLE"
;
return
undef
;
}
sub
GetLDAPPath {
my
$ldap_provider
;
my
$server_name
;
my
$ldap_path
;
my
$return_point
;
if
(
scalar
(
@_
) == 3) {
$server_name
=
$_
[0];
$ldap_path
=
"LDAP://$server_name"
;
$return_point
= 1;
}
elsif
(
scalar
(
@_
) == 4) {
$ldap_provider
=
$_
[0];
$server_name
=
$_
[1];
$return_point
= 2;
}
else
{
_ReportArgError(
"GetLDAPPath"
,
scalar
(
@_
));
return
0;
}
my
$result
;
if
(_AdodbExtendedSearch(
$server_name
,
"LDAP://$server_name"
,
"(objectClass=Computer)"
,
"rdn,distinguishedName"
,
$result
)) {
_DebugComment(
"result = $result\n"
);
if
(
$result
=~ /cn=.*,cn=Servers,cn=Configuration,ou=(.*),o=(.*)/) {
my
$returned_ou
= $1;
my
$returned_o
= $2;
$_
[
$return_point
]=
$returned_o
;
$_
[(
$return_point
+1)]=
$returned_ou
;
_DebugComment(
"ou=$returned_ou\no=$returned_o\n"
);
return
1;
}
else
{
_DebugComment(
"result = $result\n"
);
_DebugComment(
"result from ADODB search failed to produce an acceptable match\n"
);
return
0;
}
}
else
{
_DebugComment(
"ADODB search failed\n"
);
return
0;
}
}
sub
GetVersion {
my
$server_name
;
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) == 2) {
$server_name
=
$_
[0];
}
elsif
(
scalar
(
@_
) == 3) {
if
(
$_
[0] eq
"Win32::Exchange"
) {
$server_name
=
$_
[1];
}
else
{
_DebugComment(
"Error encountered processing arguments (3 args were passed)\n"
);
return
0;
}
}
else
{
_ReportArgError(
"GetVersion"
,
scalar
(
@_
));
return
0;
}
my
$serial_val
;
my
$serial_version_check_obj
= Win32::OLE->new(
'CDOEXM.ExchangeServer'
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
if
(
$error_num
eq
"0x80040154"
||
$error_num
eq
"0x800401f3"
) {
_DebugComment(
"The Exchange 2000 client tools don't look to be installed on this machine\n"
);
if
(!_E55VersionInfo(
$server_name
,
$serial_val
)) {
_DebugComment(
"Error getting version information from Exchange 5.5\n"
);
return
0;
}
}
else
{
_DebugComment(
"error: $error_num - $error_name on $server_name encountered while trying to perform GetVersion\n"
);
return
0;
}
}
else
{
_DebugComment(
"found e2k tools, so we'll look and see what version of Exchange you have.\n"
);
if
(!_E2kVersionInfo(
$server_name
,
$serial_val
)) {
_DebugComment(
"Error getting version information from Exchange 2000\n"
);
return
0;
}
}
if
(
$serial_val
=~ /Version (.*) \(Build (.*): Service Pack (.*)\)/i) {
my
%return_struct
;
$return_struct
{ver}= $1;
$return_struct
{build}= $2;
$return_struct
{sp}= $3;
if
(
scalar
(
@_
) == 2) {
%{
$_
[1]} =
%return_struct
;
}
else
{
%{
$_
[2]} =
%return_struct
;
}
return
1;
}
else
{
return
0;
}
}
sub
_E55VersionInfo {
my
$server_name
;
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) == 2) {
$server_name
=
$_
[0];
}
else
{
_ReportArgError(
"_E55VersionInfo"
,
scalar
(
@_
));
return
0;
}
my
$serial_val
;
if
(_AdodbExtendedSearch(
$server_name
,
"rootdse-configurationnamingcontext"
,
"(objectCategory=msExchExchangeServer)"
,
"name,serialNumber"
,
$serial_val
)) {
if
(
$serial_val
=~ /Version (.*) \(Build (.*): Service Pack (.*)\)/i) {
$_
[1] =
$serial_val
;
return
1;
}
else
{
_DebugComment(
"GetVersion failed to produce acceptable results (E55)\n"
);
return
0;
}
}
}
sub
_E2kVersionInfo {
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) != 2) {
_ReportArgError(
"_E2kVersionInfo"
,
scalar
(
@_
));
}
my
$server_name
=
$_
[0];
my
$exchange_server
= Win32::OLE->new(
"CDOEXM.ExchangeServer"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed creating object for version information (E2K) on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
$exchange_server
->DataSource->Open(
$server_name
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening object for version information (E2K) on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
if
(
$exchange_server
->{ExchangeVersion} ne
""
) {
$_
[1] =
$exchange_server
->{ExchangeVersion};
return
1;
}
else
{
_DebugComment(
"Failed failed to produce valid version info for $server_name\n"
);
return
0;
}
}
sub
AdodbSearch {
my
$x
;
my
$server_name
;
my
$filter
;
my
$columns
;
my
$error_num
;
my
$error_name
;
my
$return_point
;
my
$ldap_path
;
if
(
scalar
(
@_
) > 3) {
$server_name
=
$_
[0];
$filter
=
$_
[1];
$columns
=
$_
[2];
if
(
scalar
(
@_
) == 4) {
$ldap_path
=
"LDAP://$server_name"
;
$return_point
=3;
}
elsif
(
scalar
(
@_
) == 5) {
$return_point
=4;
$ldap_path
=
$_
[3];
}
else
{
_ReportArgError(
"AdodbSearch"
,
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"AdodbSearch"
,
scalar
(
@_
));
return
0;
}
my
@ado_columns
=
split
(/,/,
$columns
);
my
$Conn
= Win32::OLE->new(
"ADODB.Connection"
);
$Conn
->{
'Provider'
} =
"ADsDSOObject"
;
$Conn
->Win32::OLE::Open(
"Active Directory Provider;UID=;PWD="
);
my
$path
=
"<$ldap_path>;$filter;$columns;subtree"
;
my
$RS
=
$Conn
->Win32::OLE::Execute(
$path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"path=$ldap_path\nfilter=$filter\ncolumns=$columns\nFailed Executing ADODB Execute command on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
if
(
$RS
->RecordCount == 0) {
_DebugComment(
"path=$ldap_path\nfilter=$filter\ncolumns=$columns\nAdodbSearch yeilded no results for search on $server_name -> $error_num ($error_name)\n"
);
}
elsif
(
$RS
->RecordCount > 1) {
_DebugComment(
"path=$ldap_path\nfilter=$filter\ncolumns=$columns\nAdodbSearch yeilded more than 1 result for search on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
else
{
$_
[
$return_point
] =
$RS
->Fields(
$ado_columns
[1])->value
}
}
sub
_AdodbExtendedSearch {
my
$server_name
;
my
$path
;
my
$filter
;
my
$columns
;
my
$error_num
;
my
$error_name
;
my
$fuzzy
;
my
$return_point
;
if
(
scalar
(
@_
) > 4) {
$server_name
=
$_
[0];
$path
=
$_
[1];
$filter
=
$_
[2];
$columns
=
$_
[3];
if
(
scalar
(
@_
) == 5) {
$return_point
= 4;
}
elsif
(
scalar
(
@_
) == 6) {
$fuzzy
=
$_
[4];
$return_point
= 5;
}
}
else
{
_ReportArgError(
"_AdodbExtendedSearch ("
.
scalar
(
@_
));
return
0;
}
my
@cols
=
split
(/,/,
$columns
);
if
(
scalar
(
@cols
) != 2) {
_DebugComment(
"Only 2 columns can be sent to _AdodbExtendedSearch (total recieved = "
.
scalar
(
@cols
).
")\n"
);
}
my
$option
;
if
(
$path
=~ /^LDAP:\/\/RootDSE\/(.*)/i) {
$option
= $1;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed creating object for _AdodbExtendedSearch on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
my
$actual_ldap_path
=
$RootDSE
->Get(
$option
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed creating object for _AdodbExtendedSearch on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
$path
=
"LDAP://"
.
$actual_ldap_path
;
}
my
$string
=
"<$path>;$filter;$columns;subtree"
;
my
$Com
= Win32::OLE->new(
"ADODB.Command"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"path=$path\nfilter=$filter\ncolumns=$columns\nFailed creating ADODB.Command object for _AdodbExtendedSearch on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
my
$Conn
= Win32::OLE->new(
"ADODB.Connection"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"path=$path\nfilter=$filter\ncolumns=$columns\nFailed creating ADODB.Connection object for version information (E55) on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
$Conn
->{
'Provider'
} =
"ADsDSOObject"
;
$Conn
->Open(
"ADs Provider"
);
$Com
->{ActiveConnection} =
$Conn
;
my
$RS
=
$Conn
->Execute(
$string
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"path=$path\nfilter=$filter\ncolumns=$columns\nFailed executing ADODB.Command for version information (E55) on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
my
$not_found
= 1;
my
$search_val
;
while
(
$not_found
== 1) {
if
(
$fuzzy
== 1) {
if
(
$RS
->Fields(
$cols
[1])->value =~ /
$server_name
/i) {
if
(
ref
(
$RS
->Fields(
$cols
[1])->value) eq
"ARRAY"
) {
$search_val
= @{
$RS
->Fields(
$cols
[1])->value}[0];
}
else
{
$search_val
=
$RS
->Fields(
$cols
[1])->value;
}
$not_found
= 0;
}
}
else
{
if
(
$server_name
eq
$RS
->Fields(
$cols
[0])->value) {
if
(
ref
(
$RS
->Fields(
$cols
[1])->value) eq
"ARRAY"
) {
$search_val
= @{
$RS
->Fields(
$cols
[1])->value}[0];
}
else
{
$search_val
=
$RS
->Fields(
$cols
[1])->value;
}
$not_found
= 0;
}
}
if
(
$RS
->EOF) {
$not_found
= -1;
}
if
(
$not_found
== 1) {
$RS
->MoveNext;
}
}
if
(
$not_found
== -1) {
_DebugComment(
"Unable to match valid data for your search on $server_name\n"
);
return
0;
}
$_
[
$return_point
] =
$search_val
;
return
1;
}
sub
LocateMailboxStore {
my
$store_server
;
my
$storage_group
;
my
$mb_store
;
my
$count
=
"no"
;
if
(
$_
[0] eq
"Win32::Exchange"
) {
if
(
scalar
(
@_
) > 4) {
if
(
scalar
(
@_
) == 5) {
}
elsif
(
scalar
(
@_
) == 6) {
if
(
ref
(
$_
[5]) eq
"ARRAY"
) {
$count
=
"yes"
;
}
else
{
_DebugComment(
"the fifth argument passed to LocateMailboxStore must be an array (but is optional).\n"
);
return
0;
}
}
else
{
_ReportArgError(
"LocateMailboxStore [E2K] ("
.
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"LocateMailboxStore [E2K] ("
.
scalar
(
@_
));
return
0;
}
}
else
{
if
(
scalar
(
@_
) > 3) {
if
(
scalar
(
@_
) == 4) {
}
elsif
(
scalar
(
@_
) == 5) {
if
(
ref
(
$_
[4]) eq
"ARRAY"
) {
$count
=
"yes"
;
}
else
{
_DebugComment(
"the fifth argument passed to LocateMailboxStore must be an array (but is optional).\n"
);
return
0;
}
}
else
{
_ReportArgError(
"LocateMailboxStore [E2K] ("
.
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"LocateMailboxStore [E2K] ("
.
scalar
(
@_
));
return
0;
}
}
my
$ldap_path
;
my
$mb_count
;
my
%storage_groups
;
$store_server
=
$_
[0];
$storage_group
=
$_
[1];
$mb_store
=
$_
[2];
if
(_EnumStorageGroups(
$store_server
,\
%storage_groups
)) {
if
(
$count
eq
"yes"
) {
foreach
my
$sg
(
keys
%storage_groups
) {
$mb_count
+=
scalar
(
keys
%{
$storage_groups
{
$sg
}});
}
push
(@{
$_
[4]},
scalar
(
keys
%storage_groups
));
push
(@{
$_
[4]},
$mb_count
);
}
if
(_TraverseStorageGroups(\
%storage_groups
,
$store_server
,
$storage_group
,
$mb_store
,
$ldap_path
)) {
$_
[3] =
$ldap_path
;
return
1;
}
else
{
_DebugComment(
"Unable to locate valid mailbox store for mailbox creation.\n"
);
return
0;
}
}
else
{
_DebugComment(
"Unable to locate valid storage group for mailbox creation.\n"
);
return
0;
}
}
sub
_EnumStorageGroups {
my
$server_name
;
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) == 2) {
$server_name
=
$_
[0];
}
else
{
_ReportArgError(
"_EnumStorageGroups ("
.
scalar
(
@_
));
return
0;
}
my
$exchange_server
= Win32::OLE->new(
"CDOEXM.ExchangeServer"
);
$exchange_server
->DataSource->Open(
$server_name
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening ADODB ExchangeServer object for Storage Group enumeration on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
my
@storegroups
= Win32::OLE::in(
$exchange_server
->StorageGroups);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed enumerating Storage Groups on $server_name -> $error_num ($error_name)\n"
);
return
0;
}
my
%storage_groups
;
my
$stor_group_obj
= Win32::OLE->new(
"CDOEXM.StorageGroup"
);
my
$mbx_store_obj
= Win32::OLE->new(
"CDOEXM.MailboxStoreDB"
);
foreach
my
$storegroup
(
@storegroups
) {
$stor_group_obj
->DataSource->Open(
$storegroup
);
_DebugComment(
"Stor Name = "
.
$stor_group_obj
->{Name}.
"\n"
);
foreach
my
$mbx_store
(Win32::OLE::in(
$stor_group_obj
->{MailboxStoreDBs})) {
$mbx_store_obj
->DataSource->Open(
$mbx_store
);
_DebugComment(
" Mailbox Store = $mbx_store_obj->{Name}\n"
);
$storage_groups
{
$stor_group_obj
->{Name}}{
$mbx_store_obj
->{Name}}=
$mbx_store
;
}
}
%{
$_
[1]} =
%storage_groups
;
return
1;
}
sub
_TraverseStorageGroups {
if
(
scalar
(
@_
) != 5) {
_ReportArgError(
"_TraverseStorageGroups [E2K] ("
.
scalar
(
@_
));
return
0;
}
if
(
ref
(
$_
[0]) ne
"HASH"
) {
_DebugComment(
"Storage group object is not a hash\n"
);
return
0;
}
my
%storage_groups
= %{
$_
[0]};
my
$info_store_server
=
$_
[1];
my
$storage_group
=
$_
[2];
my
$mb_store
=
$_
[3];
my
$ldap_path
;
if
(
scalar
(
keys
%storage_groups
) == 0) {
_DebugComment(
"No Storage Groups were found\n"
);
return
0;
}
my
$sg
;
my
$mb
;
foreach
$sg
(
keys
%storage_groups
) {
if
(
scalar
(
keys
%storage_groups
) == 1) {
foreach
$mb
(
keys
%{
$storage_groups
{
$sg
}}) {
if
(
scalar
(
keys
%{
$storage_groups
{
$sg
}}) == 1 ||
$mb
eq
$mb_store
&&
$mb_store
ne
""
) {
$_
[4] =
"LDAP://$info_store_server/"
.
$storage_groups
{
$sg
}{
$mb
};
return
1;
}
else
{
next
;
}
}
_DebugComment(
"Error locating proper storage group and mailbox db for mailbox creation (1SG)\n"
);
return
0;
}
elsif
(
$sg
eq
$storage_group
&&
$storage_group
ne
""
) {
foreach
$mb
(
keys
%{
$storage_groups
{
$sg
}}) {
if
(
scalar
(
keys
%{
$storage_groups
{
$sg
}}) == 1 ||
$mb
eq
$mb_store
&&
$mb_store
ne
""
) {
$_
[4] =
"LDAP://$info_store_server/"
.
$storage_groups
{
$sg
}{
$mb
};
return
1;
}
else
{
next
;
}
}
_DebugComment(
"Error locating proper storage group and mailbox db for mailbox creation (2+SG)\n"
);
return
0;
}
}
}
sub
CreateMailbox {
my
$error_num
;
my
$error_name
;
my
$mbx
;
my
$provider
=
$_
[0];
bless
$provider
,
"Win32::OLE"
;
Win32::OLE->LastError(0);
my
$type
= Win32::OLE->QueryObjectType(
$provider
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"failed querying OLE Object for Exchange Server Determination for CreateMailbox ($error_num)\n"
);
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
bless
$provider
,
"Win32::Exchange"
;
if
(
$type
eq
"IPerson"
) {
if
(
$mbx
= _E2KCreateMailbox(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$mbx
;
}
}
else
{
if
(
$mbx
= _E55CreateMailbox(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$mbx
;
}
}
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
sub
_E55CreateMailbox {
my
$ldap_provider
;
my
$information_store_server
;
my
$mailbox_alias_name
;
my
$org
;
my
$ou
;
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) > 2) {
$ldap_provider
=
$_
[0];
$information_store_server
=
$_
[1];
$mailbox_alias_name
=
$_
[2];
if
(
scalar
(
@_
) == 3) {
if
(
$ldap_provider
->GetLDAPPath(
$information_store_server
,
$org
,
$ou
)) {
_DebugComment(
"returned -> o=$org,ou=$ou\n"
);
}
else
{
_DebugComment(
"Error Returning from GetLDAPPath\n"
);
return
0;
}
}
elsif
(
scalar
(
@_
) == 5) {
$org
=
$_
[3];
$ou
=
$_
[4];
}
else
{
_ReportArgError(
"CreateMailbox [5.5] ("
.
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"CreateMailbox [5.5] ("
.
scalar
(
@_
));
return
0;
}
my
$recipients_path
=
"LDAP://$information_store_server/cn=Recipients,ou=$ou,o=$org"
;
_DebugComment(
"$recipients_path\n"
);
bless
$ldap_provider
,
"Win32::OLE"
;
my
$Recipients
=
$ldap_provider
->GetObject(
""
,
$recipients_path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening recipients path on $information_store_server\n"
);
return
0;
}
my
$original_ole_warn_value
=
$Win32::OLE::Warn
;
$Win32::OLE::Warn
= 0;
$Recipients
->GetObject(
"organizationalPerson"
,
"cn=$mailbox_alias_name"
);
if
(!_ErrorCheck(
"0x80072030"
,
$error_num
,
$error_name
)) {
if
(
$error_num
eq
"0x00000000"
) {
_DebugComment(
"$error_num - Mailbox already exists on $information_store_server\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
0;
}
else
{
_DebugComment(
"Unable to lookup object $mailbox_alias_name on $information_store_server ($error_num)\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
0;
}
}
_DebugComment(
" Box Does Not Exist (This is good)\n"
);
bless
$ldap_provider
,
"Win32::Exchange"
;
my
$new_mailbox
=
$Recipients
->Create(
"organizationalPerson"
,
"cn=$mailbox_alias_name"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error creating Mailbox -> $error_num ($error_name)\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
0;
}
my
%attrs
;
$attrs
{
'uid'
}=
$mailbox_alias_name
;
$attrs
{
'mailPreferenceOption'
}=
"0"
;
$attrs
{
'MAPI-Recipient'
}=
'TRUE'
;
$attrs
{
'MDB-Use-Defaults'
}=
"TRUE"
;
$attrs
{
'givenName'
}=
"Exchange"
;
$attrs
{
'sn'
}=
"Mailbox"
;
$attrs
{
'cn'
}=
"Exchange $mailbox_alias_name Mailbox"
;
$attrs
{
'Home-MTA'
}=
"cn=Microsoft MTA,cn=$information_store_server,cn=Servers,cn=Configuration,ou=$ou,o=$org"
;
$attrs
{
'Home-MDB'
}=
"cn=Microsoft Private MDB,cn=$information_store_server,cn=Servers,cn=Configuration,ou=$ou,o=$org"
;
foreach
my
$attr
(
keys
%attrs
) {
$new_mailbox
->Put(
$attr
=>
$attrs
{
$attr
});
}
$new_mailbox
->SetInfo;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting attribute on mailbox -> $error_num ($error_name)\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
0;
}
_DebugComment(
" -Mailbox created...\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
$new_mailbox
;
}
sub
_E2KCreateMailbox {
my
$error_num
;
my
$error_name
;
my
$provider
;
my
$info_store_server
;
my
$pdc
;
my
$nt_pdc
;
my
$mailbox_alias_name
;
my
$mail_domain
;
my
$storage_group
;
my
$mb_store
;
my
$mailbox_ldap_path
;
if
(
scalar
(
@_
) >4) {
$provider
=
$_
[0];
$info_store_server
=
$_
[1];
$nt_pdc
=
$_
[2];
$mailbox_alias_name
=
$_
[3];
if
(
scalar
(
@_
) == 5) {
}
elsif
(
scalar
(
@_
) == 6) {
$mailbox_ldap_path
=
$_
[5]
}
elsif
(
scalar
(
@_
) == 7) {
$storage_group
=
$_
[5];
$mb_store
=
$_
[6];
}
else
{
_ReportArgError(
"CreateMailbox [E2K] ("
.
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"CreateMailbox [E2K] ("
.
scalar
(
@_
));
return
0;
}
_StripBackslashes(
$nt_pdc
,
$pdc
);
my
$user_dist_name
;
if
(!AdodbSearch(
$pdc
,
"(samAccountName=$mailbox_alias_name)"
,
"samAccountName,distinguishedName"
,
$user_dist_name
)) {
_DebugComment(
"Error querying distinguished name for user in CreateMailbox (E2K)\n"
);
return
0;
}
bless
$provider
,
"Win32::OLE"
;
my
$user_account
=
$provider
->DataSource->Open(
"LDAP://$pdc/$user_dist_name"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening NT user account for new mailbox creation on $pdc ($error_num)\n"
);
return
0;
}
my
$info_store
=
$provider
->GetInterface(
"IMailboxStore"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening mailbox interface on $pdc ($error_num)\n"
);
if
(
$error_num
eq
"0x80004002"
) {
_DebugComment(
"Error: No such interface supported.\n Note: Make sure you have the Exchange System Manager loaded on this system\n"
);
}
return
0;
}
if
(
$mailbox_ldap_path
eq
""
) {
if
(!LocateMailboxStore(
$info_store_server
,
$storage_group
,
$mb_store
,
$mailbox_ldap_path
)) {
return
0;
}
}
_DebugComment(
"$mailbox_ldap_path\n"
);
$info_store
->CreateMailbox(
$mailbox_ldap_path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed creating mailbox for $mailbox_alias_name ($error_num) $error_name\n"
);
return
0;
}
$provider
->DataSource->Save();
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed saving mailbox for $mailbox_alias_name\n"
);
return
0;
}
return
$provider
;
}
sub
GetDistinguishedName {
my
$server_name
;
my
$filter
;
my
$filter_name
;
my
$result
;
if
(
scalar
(
@_
) == 3) {
$server_name
=
$_
[0];
$filter
=
$_
[1];
}
else
{
_ReportArgError(
"GetDistinguishedName"
,
scalar
(
@_
));
}
my
%filters
;
%filters
= (
'Home-MDB'
=>
"(objectClass=MHS-Message-Store)"
,
'Home-MTA'
=>
"(objectClass=MTA)"
,
);
if
(
defined
(
$filters
{
$filter
})) {
$filter_name
=
$filters
{
$filter
};
}
else
{
$filter_name
=
$filter
;
}
if
(_AdodbExtendedSearch(
$server_name
,
"LDAP://$server_name"
,
$filter_name
,
"cn,distinguishedName"
,1,
$result
)) {
$_
[2] =
$result
;
return
0;
}
else
{
return
0;
}
}
sub
_StripBackslashes {
my
$nt_pdc
=
$_
[0];
if
(
$nt_pdc
=~ /^\\\\(.*)/) {
$_
[1] = $1;
return
1;
}
else
{
$_
[1] =
$nt_pdc
;
return
1;
}
}
sub
GetMailbox {
my
$error_num
;
my
$error_name
;
my
$mbx
;
my
$provider
=
$_
[0];
bless
$provider
,
"Win32::OLE"
;
Win32::OLE->LastError(0);
my
$type
= Win32::OLE->QueryObjectType(
$provider
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"failed querying OLE Object for Exchange Server Determination for CreateMailbox\n"
);
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
bless
$provider
,
"Win32::Exchange"
;
if
(
$type
eq
"IPerson"
) {
if
(
$mbx
= _E2KGetMailbox(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$mbx
;
}
}
else
{
if
(
$mbx
= _E55GetMailbox(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$mbx
;
}
}
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
sub
_E55GetMailbox {
my
$ldap_provider
;
my
$information_store_server
;
my
$mailbox_alias_name
;
my
$org
;
my
$ou
;
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) > 2) {
$ldap_provider
=
$_
[0];
$information_store_server
=
$_
[1];
$mailbox_alias_name
=
$_
[2];
if
(
scalar
(
@_
) == 3) {
if
(
$ldap_provider
->GetLDAPPath(
$information_store_server
,
$org
,
$ou
)) {
_DebugComment(
"returned -> o=$org,ou=$ou\n"
);
}
else
{
_DebugComment(
"Error Returning from GetLDAPPath\n"
);
return
0;
}
}
elsif
(
scalar
(
@_
) == 5) {
$org
=
$_
[3];
$ou
=
$_
[4];
}
else
{
_ReportArgError(
"GetMailbox [5.5]"
,
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"GetMailbox [5.5] "
,
scalar
(
@_
));
return
0;
}
my
$recipients_path
=
"LDAP://$information_store_server/cn=Recipients,ou=$ou,o=$org"
;
bless
$ldap_provider
,
"Win32::OLE"
;
my
$Recipients
=
$ldap_provider
->GetObject(
""
,
$recipients_path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening recipients path on $information_store_server\n"
);
return
0;
}
my
$original_ole_warn_value
=
$Win32::OLE::Warn
;
$Win32::OLE::Warn
= 0;
my
$mailbox
=
$Recipients
->GetObject(
"organizationalPerson"
,
"cn=$mailbox_alias_name"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Unable to Get the mailbox object for $mailbox_alias_name on $information_store_server ($error_num)\n"
);
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
0;
}
$Win32::OLE::Warn
=
$original_ole_warn_value
;
return
$mailbox
;
}
sub
_E2KGetMailbox {
my
$error_num
;
my
$error_name
;
my
$provider
;
my
$mailbox_alias_name
;
my
$nt_dc
;
my
$dc
;
if
(
scalar
(
@_
) == 3) {
$provider
=
$_
[0];
$nt_dc
=
$_
[1];
$mailbox_alias_name
=
$_
[2];
}
else
{
_ReportArgError(
"GetMailbox [E2K]"
,
scalar
(
@_
));
return
0;
}
_StripBackslashes (
$nt_dc
,
$dc
);
my
$user_dist_name
;
if
(!AdodbSearch(
$dc
,
"(samAccountName=$mailbox_alias_name)"
,
"samAccountName,distinguishedName"
,
$user_dist_name
)) {
_DebugComment(
"Error querying distinguished name for user in GetMailbox (E2K)\n"
);
return
0;
}
bless
$provider
,
"Win32::OLE"
;
$provider
->DataSource->Open(
"LDAP://$dc/$user_dist_name"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening AD user account for mailbox retrieval on $dc ($error_num)\n"
);
return
0;
}
my
$user_obj_path
=
$provider
->DataSource->{SourceURL};
my
$user_obj
= Win32::OLE->GetObject(
$user_obj_path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed opening SourceURL for GetMailbox ($error_num)\n"
);
return
0;
}
if
(
$user_obj
->{homeMDB} eq
""
) {
_DebugComment(
"Error performing GetMailbox.. mailbox does not exist ($error_num)\n"
);
return
0;
}
else
{
$provider
->DataSource->Save();
return
$provider
;
}
}
sub
SetAttributes {
my
$error_num
;
my
$error_name
;
my
$provider
=
$_
[0];
bless
$provider
,
"Win32::OLE"
;
Win32::OLE->LastError(0);
my
$type
= Win32::OLE->QueryObjectType(
$provider
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"failed querying OLE Object type for Exchange Server Determination during call to SetAttributes\n"
);
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
bless
$provider
,
"Win32::Exchange"
;
my
$rtn
;
if
(
$type
eq
"IPerson"
) {
if
(
$rtn
= _E2KSetAttributes(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
else
{
if
(
$rtn
= _E55SetAttributes(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
sub
_E2KSetAttributes {
my
$error_num
;
my
$error_name
;
my
%attrs
;
my
$user_account
;
my
$mailbox
;
if
(
scalar
(
@_
) == 2) {
$user_account
=
$_
[0];
if
(
ref
(
$_
[1]) ne
"HASH"
) {
_DebugComment(
"second object passed to SetAttributes was not a HASH reference -> $error_num ($error_name)\n"
);
return
0;
}
else
{
%attrs
= %{
$_
[1]};
}
}
else
{
_ReportArgError(
"SetAttributes [2K]"
,
scalar
(
@_
));
return
0;
}
bless
$user_account
,
"Win32::OLE"
;
foreach
my
$interface
(
keys
%attrs
) {
my
$mailbox_interface
=
$user_account
->GetInterface(
$interface
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error getting mailbox interface -> $error_num ($error_name)\n"
);
return
0;
}
foreach
my
$attr
(
keys
%{
$attrs
{
$interface
}}) {
$mailbox_interface
->{
$attr
} =
$attrs
{
$interface
}{
$attr
};
}
$user_account
->DataSource->Save();
}
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting attribute on mailbox -> $error_num ($error_name)\n"
);
return
0;
}
return
1;
}
sub
SetOwner {
my
$error_num
;
my
$error_name
;
my
$dc
;
if
(
scalar
(
@_
) != 2) {
_ReportArgError(
"SetOwner [5.5]"
,
scalar
(
@_
));
return
0;
}
my
$new_mailbox
=
$_
[0];
my
$username
=
$_
[1];
if
(
$username
=~ /(.*)\\(.*)/) {
$dc
=$1;
$username
= $2;
}
else
{
_DebugComment(
"error parsing username to extract domain and username\n"
);
return
0;
}
my
$sid
= Win32::OLE->new(
"ADsSID"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error creating security object (ADsSID) -> $error_num ($error_name)\n"
);
return
0;
}
$sid
->SetAs(
$ADS_SID_WINNT_PATH
,
"WinNT://$dc/$username,user"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting security object at an ADS_SID_WINNT_PATH -> $error_num ($error_name)\n"
);
return
0;
}
my
$sidHex
=
$sid
->GetAs(
$ADS_SID_HEXSTRING
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error converting security object at an ADS_SID_HEXSTRING -> $error_num ($error_name)\n"
);
return
0;
}
bless
$new_mailbox
,
"Win32::OLE"
;
$new_mailbox
->Put(
"Assoc-NT-Account"
,
$sidHex
);
$new_mailbox
->SetInfo;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting owner information on mailbox -> $error_num ($error_name)\n"
);
bless
$new_mailbox
,
"Win32::Exchange"
;
return
0;
}
bless
$new_mailbox
,
"Win32::Exchange"
;
return
1;
}
sub
SetPerms {
my
$error_num
;
my
$error_name
;
my
$provider
=
$_
[0];
bless
$provider
,
"Win32::OLE"
;
Win32::OLE->LastError(0);
my
$type
= Win32::OLE->QueryObjectType(
$provider
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"failed querying OLE Object type for Exchange Server Determination during call to SetAttributes\n"
);
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
bless
$provider
,
"Win32::Exchange"
;
my
$rtn
;
if
(
$type
eq
"IPerson"
) {
if
(
$rtn
= _E2KSetPerms(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
else
{
if
(
$rtn
= _E55SetPerms(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
sub
_E55SetPerms {
if
(
scalar
(
@_
) != 2) {
_ReportArgError(
"SetPerms [5.5]"
,
scalar
(
@_
));
return
0;
}
if
(
ref
(
$_
[1]) ne
"ARRAY"
) {
_DebugComment(
"permissions list must be an array reference (e55)\n"
);
return
0;
}
my
$new_mailbox
=
$_
[0];
my
@perms_list
= @{
$_
[1]};
my
$sec
= Win32::OLE->CreateObject(
"ADsSecurity"
);
my
$error_num
;
my
$error_name
;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error creating security object (ADSSecurity) -> $error_num ($error_name)\n"
);
if
(
$error_num
eq
"0x80004002"
) {
_DebugComment(
"Error: No such interface supported.\n Note: Make sure you have the ADSSecurity.DLL from the ADSI SDK regisered on this system\n"
);
}
return
0;
}
bless
$new_mailbox
,
"Win32::OLE"
;
my
$sd
=
$sec
->GetSecurityDescriptor(
$new_mailbox
->{ADsPath});
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error querying security descriptor for mailbox -> $error_num ($error_name)\n"
);
return
0;
}
my
$dacl
=
$sd
->{DiscretionaryAcl};
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error querying discretionary acl for mailbox -> $error_num ($error_name)\n"
);
return
0;
}
foreach
my
$userid
(
@perms_list
) {
_DebugComment(
" -Setting perms for $userid\n"
);
my
$ace
= Win32::OLE->CreateObject(
"AccessControlEntry"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error creating access control entry for mailbox -> $error_num ($error_name)\n"
);
return
0;
}
my
%properties
;
$properties
{Trustee}=
$userid
;
$properties
{AccessMask}=
$ADS_RIGHT_EXCH_MODIFY_USER_ATT
|
$ADS_RIGHT_EXCH_MAIL_SEND_AS
|
$ADS_RIGHT_EXCH_MAIL_RECEIVE_AS
;
$properties
{AceType}=
$ADS_ACETYPE_ACCESS_ALLOWED
;
foreach
my
$property
(
keys
%properties
) {
$ace
->LetProperty(
$property
,
$properties
{
$property
});
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting $property for mailbox -> $error_num ($error_name)\n"
);
return
0;
}
}
$dacl
->AddAce(
$ace
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error adding access control entry to perms list -> $error_num ($error_name)\n"
);
return
0;
}
}
$sd
->LetProperty(
"DiscretionaryAcl"
,
$dacl
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting discretionary acl on security security descriptor -> $error_num ($error_name)\n"
);
return
0;
}
$sec
->SetSecurityDescriptor(
$sd
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting security descriptor on security object -> $error_num ($error_name)\n"
);
return
0;
}
$new_mailbox
->SetInfo;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting permissions on mailbox -> $error_num ($error_name)\n"
);
return
0;
}
return
1;
}
sub
_E2KSetPerms {
my
$error_num
;
my
$error_name
;
if
(
scalar
(
@_
) != 2) {
_ReportArgError(
"SetPerms [2K]"
,
scalar
(
@_
));
return
0;
}
if
(
ref
(
$_
[1]) ne
"ARRAY"
) {
_DebugComment(
"permissions list must be an array reference (e2k)\n"
);
return
0;
}
my
$cdo_user_obj
=
$_
[0];
my
@perms_list
= @{
$_
[1]};
bless
$cdo_user_obj
,
"Win32::OLE"
;
my
$ldap_user_path
=
$cdo_user_obj
->{DataSource}->{SourceURL};
my
$ldap_user_obj
= Win32::OLE->GetObject(
$ldap_user_path
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error querying Source URL for CDO.Person object ($error_num)\n"
);
return
0;
}
my
$sd
=
$ldap_user_obj
->{
'MailboxRights'
};
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error querying MailboxRights property ($error_num) - make sure you are using Exchange 2000 SP1+hotfix or higher [server & client]\n"
);
return
0;
}
my
$dacl
=
$sd
->{DiscretionaryAcl};
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error getting DiscretionaryAcl ($error_num)\n"
);
return
0;
}
foreach
my
$user_account
(
@perms_list
) {
my
$domain
;
my
$username
;
if
(
$user_account
=~ /(.*)\\(.*)/) {
$domain
= $1;
$username
= $2;
}
else
{
_DebugComment(
"error parsing user object (expected DOMAIN\\Username) -> $error_num ($error_name)\n"
);
return
0;
}
my
$Ace
= Win32::OLE->new(
"AccessControlEntry"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error creating new ACE ($error_num)\n"
);
return
0;
}
my
%properties
;
$properties
{AccessMask}=
$ADS_RIGHT_DS_CREATE_CHILD
;
$properties
{AceType}=
$ADS_ACETYPE_ACCESS_ALLOWED
;
$properties
{AceFlags}=
$ADS_ACEFLAG_INHERIT_ACE
;
$properties
{Flags}=0;
$properties
{Trustee}=
$user_account
;
$properties
{ObjectType}=0;
$properties
{InheritedObjectType}=0;
foreach
my
$property
(
keys
%properties
) {
if
(
$property
=~ /(ObjectType|InheritedObjectType)/ &&
$properties
{
$property
} == 0) {
next
;
}
$Ace
->LetProperty(
$property
,
$properties
{
$property
});
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error setting $property ($error_num)\n"
);
return
0;
}
}
$dacl
->AddAce(
$Ace
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error adding AccessControlEntry to AccessControlList: ($error_num)\n"
);
return
0;
}
}
$sd
->LetProperty(
'DiscretionaryAcl'
,
$dacl
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error setting AccessControlList to Security Descriptor: ($error_num)\n"
);
return
0;
}
$ldap_user_obj
->LetProperty(
'MailboxRights'
,
$sd
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error setting Security Descriptor to Mailbox Security entry: ($error_num)\n"
);
return
0;
}
$ldap_user_obj
->SetInfo();
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error setting Security Descriptor to Mailbox Security entry: ($error_num)\n"
);
return
0;
}
return
1;
}
sub
AddDLMembers {
my
$error_num
;
my
$error_name
;
my
$provider
=
$_
[0];
bless
$provider
,
"Win32::OLE"
;
Win32::OLE->LastError(0);
my
$type
= Win32::OLE->QueryObjectType(
$provider
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"failed querying OLE Object type for Exchange Server Determination during call to SetAttributes\n"
);
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
bless
$provider
,
"Win32::Exchange"
;
my
$rtn
;
if
(
$type
eq
"IPerson"
) {
if
(
$rtn
= _E2KAddDLMembers(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
else
{
if
(
$rtn
= _E55AddDLMembers(
@_
)) {
bless
$provider
,
"Win32::Exchange"
;
return
$rtn
;
}
}
bless
$provider
,
"Win32::Exchange"
;
return
0;
}
sub
_E55AddDLMembers {
my
$ldap_provider
;
my
$server_name
;
my
$exch_dl_name
;
my
@new_members
;
my
$ou
;
my
$org
;
if
(
scalar
(
@_
) > 3) {
$ldap_provider
=
$_
[0];
$server_name
=
$_
[1];
$exch_dl_name
=
$_
[2];
if
(
ref
(
$_
[3]) ne
"ARRAY"
) {
_DebugComment(
"members list must be an array reference\n"
);
return
0;
}
@new_members
=@{
$_
[3]};
if
(
scalar
(
@_
) == 4) {
if
(
$ldap_provider
->GetLDAPPath(
$server_name
,
$org
,
$ou
)) {
_DebugComment(
"returned -> o=$org,ou=$ou\n"
);
}
else
{
_DebugComment(
"Error Returning from GetLDAPPath\n"
);
return
0;
}
}
elsif
(
scalar
(
@_
) == 6) {
$org
=
$_
[3];
$ou
=
$_
[4];
}
else
{
_ReportArgError(
"AddDLMembers [5.5]"
,
scalar
(
@_
));
return
0;
}
}
else
{
_ReportArgError(
"AddDLMembers [5.5]"
,
scalar
(
@_
));
return
0;
}
my
$temp_exch_dl
;
my
$original_ole_warn_value
=
$Win32::OLE::Warn
;
bless
$ldap_provider
,
"Win32::OLE"
;
my
$exch_dl
=
$ldap_provider
->GetObject(
""
,
"LDAP://$server_name/cn=$exch_dl_name,cn=Distribution Lists,ou=$ou,o=$org"
);
my
$error_num
;
my
$error_name
;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error querying distribution list ($exch_dl_name) -> $error_num ($error_name)\n"
);
return
0;
}
my
$exch_members
=
$exch_dl
->{
'member'
};
if
(
ref
(
$exch_members
) eq
"ARRAY"
) {
_DebugComment(
" -Array (2 or more members exist)\n"
);
}
else
{
_DebugComment(
" -(Less than 2 members are named in this distribution list)\n"
);
my
$temp_exch_dl
=
$exch_members
;
undef
(
$exch_members
);
if
(
$temp_exch_dl
) {
_DebugComment(
" -1 member exists\n"
);
push
(
@$exch_members
,
$temp_exch_dl
);
}
else
{
_DebugComment(
" -0 members exists\n"
);
}
}
foreach
my
$username
(
@new_members
) {
_DebugComment(
" -Adding $username to Distribution List: $exch_dl_name\n"
);
my
$duplicate
;
foreach
my
$dup
(
@$exch_members
) {
if
(
lc
(
$dup
) =~
lc
(
"cn=$username,cn=Recipients,ou=$ou,o=$org"
)) {
$duplicate
= 1;
last
;
}
}
if
(
$duplicate
!= 1) {
push
(
@$exch_members
,
"cn=$username,cn=Recipients,ou=$ou,o=$org"
);
}
}
$exch_dl
->Put(
'member'
,
$exch_members
);
$exch_dl
->SetInfo;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"error setting new member for distribution list ($exch_dl_name) -> $error_num ($error_name)\n"
);
return
0;
}
return
1;
}
sub
_E2KAddDLMembers {
if
(
scalar
(
@_
) != 3) {
_ReportArgError(
"AddDLMembers (E2K)"
,
scalar
(
@_
));
return
0;
}
if
(
ref
(
$_
[2]) ne
"ARRAY"
) {
_DebugComment(
"Third argument is the list of users you want to add to this DL, and should be an array reference, but instead, it was a(an): "
.
ref
(
$_
[2]).
" reference\n"
);
return
0;
}
my
$error_num
;
my
$error_name
;
my
$group_dn
;
my
$user_dn
;
my
$provider
=
$_
[0];
my
$group
=
$_
[1];
my
@user_list
= @{
$_
[2]};
if
(!Win32::Exchange::_AdodbExtendedSearch(
$group
,
"LDAP://RootDSE/dnsHostName"
,
"(objectClass=group)"
,
"samAccountName,distinguishedName"
,
$group_dn
)) {
_DebugComment(
"Failed Adodb search for dist list\n"
);
return
0;
}
foreach
my
$username
(
@user_list
) {
if
(!Win32::Exchange::_AdodbExtendedSearch(
$username
,
"LDAP://RootDSE/dnsHostName"
,
"(objectClass=user)"
,
"samAccountName,distinguishedName"
,
$user_dn
)) {
_DebugComment(
"Failed Adodb search for user\n"
);
return
0;
}
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Failed Getting RootDSE ($error_num)\n"
);
return
0;
}
my
$dc
=
$RootDSE
->Get(
"dnsHostName"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error getting RootDSE dns host name ($error_num)\n"
);
return
0;
}
my
@dc_array
=
split
(/\./,
$dc
);
my
$ldap_obj
= Win32::OLE->new(
"ADsNamespaces"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error creating new ADsNamespaces object ($error_num)\n"
);
return
0;
}
my
$group_obj
=
$ldap_obj
->GetObject(
""
,
"LDAP://$dc_array[0]/$group_dn"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error opening distribution list on $dc_array[0] ($error_num)\n"
);
return
0;
}
$group_obj
->Add(
"LDAP://$dc_array[0]/$user_dn"
);
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
if
(
$error_num
eq
"0x80071392"
) {
_DebugComment(
"Error adding user ($username) to distribution list [they are already a member]\n"
);
}
else
{
_DebugComment(
"Error adding user ($username) to distribution list ($error_num)\n"
);
return
0;
}
}
$group_obj
->SetInfo;
if
(!_ErrorCheck(
"0x00000000"
,
$error_num
,
$error_name
)) {
_DebugComment(
"Error committing addition to distribution list ($error_num)\n"
);
return
0;
}
}
return
1;
}
sub
_ErrorCheck {
my
$last_error_expected
=
$_
[0];
my
$error_num
;
my
$error_name
;
my
$last_ole_error
= Win32::OLE->LastError();
$error_num
=
sprintf
(
"0x%08x"
,
$last_ole_error
);
my
@error_list
=
split
(/\"/,
$last_ole_error
,3);
$error_name
=
$error_list
[1];
if
(
$error_num
ne
$last_error_expected
) {
$_
[1] =
$error_num
;
$_
[2] =
$error_name
;
return
0;
}
else
{
return
1;
}
}
sub
_ReportArgError {
_DebugComment(
"incorrect number of options passed to $_[0] ($_[1])\n"
);
return
1;
}
sub
_DebugComment {
print
"$_[0]"
if
(
$DEBUG
== 1);
return
1;
}
1;