You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
767 lines
24 KiB
767 lines
24 KiB
// AccntCmt.cpp : Implementation of CAddUser_AccntCommit
|
|
#include "stdafx.h"
|
|
#include "AU_Accnt.h"
|
|
#include "AccntCmt.h"
|
|
|
|
#include <dsgetdc.h>
|
|
#include <lm.h>
|
|
#include <lmshare.h>
|
|
#include <Aclapi.h>
|
|
#include <atlcom.h>
|
|
|
|
// ldap/adsi includes
|
|
#include <iads.h>
|
|
#include <adshlp.h>
|
|
#include <adsiid.h>
|
|
|
|
#include <proputil.h>
|
|
#include <CreateEmailName.h>
|
|
#include <P3admin.h>
|
|
#include <CheckUser.h>
|
|
|
|
// POP3 Defines
|
|
#define SZ_AUTH_ID_MD5_HASH _T("c395e20c-2236-4af7-b736-54fad07dc526")
|
|
|
|
// Defines for account flags.
|
|
#define PASSWD_NOCHANGE 0x01
|
|
#define PASSWD_CANCHANGE 0x02
|
|
#define PASSWD_MUSTCHANGE 0x04
|
|
|
|
#ifndef CHECK_HR
|
|
|
|
#define CHECK_HR( x ) CHECK_HR_RET( x, _hr );
|
|
#define CHECK_HR_RET( x, y ) \
|
|
{ \
|
|
HRESULT _hr = x; \
|
|
if( FAILED(_hr) ) \
|
|
{ \
|
|
_ASSERT( !_T("CHECK_HR_RET() failed. calling TRACE() with HRESULT and statement") ); \
|
|
return y; \
|
|
} \
|
|
}
|
|
|
|
#endif // CHECK_HRhr;
|
|
|
|
// ****************************************************************************
|
|
// CAddUser_AccntCommit
|
|
// ****************************************************************************
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// WriteErrorResults()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CAddUser_AccntCommit::WriteErrorResults( IPropertyPagePropertyBag* pPPPBag )
|
|
{
|
|
// ------------------------------------------------------------------------
|
|
// Write the the values to the property bag.
|
|
// ------------------------------------------------------------------------
|
|
if( FAILED(WriteInt4 ( pPPPBag, PROP_ACCNT_ERROR_CODE_GUID_STRING, m_dwErrCode, FALSE )) )
|
|
{
|
|
_ASSERT(FALSE);
|
|
}
|
|
if( FAILED(WriteString( pPPPBag, PROP_ACCNT_ERROR_STR_GUID_STRING, m_csErrStr, FALSE )) )
|
|
{
|
|
_ASSERT(FALSE);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// SetErrCode()
|
|
// ----------------------------------------------------------------------------
|
|
void CAddUser_AccntCommit::SetErrCode( DWORD dwCode )
|
|
{
|
|
m_dwErrCode |= dwCode;
|
|
return;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// SetErrorResults()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CAddUser_AccntCommit::SetErrorResults( DWORD dwErrType, BOOL bPOP3 /* = FALSE */ )
|
|
{
|
|
SetErrCode(dwErrType);
|
|
|
|
CString csTemp;
|
|
|
|
switch( dwErrType )
|
|
{
|
|
case ERROR_CREATION:
|
|
case ERROR_PROPERTIES:
|
|
{
|
|
m_csErrStr.LoadString(IDS_ERROR_CREATING_USER);
|
|
break;
|
|
}
|
|
case ERROR_MAILBOX:
|
|
{
|
|
csTemp.LoadString( IDS_ERROR_POP3MAILBOX);
|
|
m_csErrStr += csTemp;
|
|
break;
|
|
}
|
|
case ERROR_PASSWORD:
|
|
{
|
|
csTemp.LoadString(IDS_ERROR_PASSWORD);
|
|
m_csErrStr += csTemp;
|
|
break;
|
|
}
|
|
case ERROR_DUPE:
|
|
{
|
|
csTemp.LoadString(IDS_ERROR_DUPLICATE);
|
|
m_csErrStr += csTemp;
|
|
break;
|
|
}
|
|
case ERROR_MEMBERSHIPS:
|
|
{
|
|
csTemp.LoadString(IDS_ERROR_MEMBERSHIP);
|
|
m_csErrStr += csTemp;
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
m_dwErrCode = 0;
|
|
m_csErrStr = _T("");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Commit()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CAddUser_AccntCommit::Commit( IDispatch* pdispPPPBag )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
HRESULT hrAdmin = IsUserInGroup( DOMAIN_ALIAS_RID_ADMINS );
|
|
if( hrAdmin != S_OK )
|
|
{
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
CComPtr<IPropertyPagePropertyBag> spPPPBag = NULL;
|
|
hr = pdispPPPBag->QueryInterface( __uuidof(IPropertyPagePropertyBag), (void**)&spPPPBag );
|
|
if ( !spPPPBag )
|
|
return hr;
|
|
|
|
BOOL bRO = FALSE;
|
|
BOOL bPOP3 = FALSE;
|
|
|
|
ReadBool( spPPPBag, PROP_POP3_CREATE_MB_GUID_STRING, &bPOP3, &bRO );
|
|
|
|
// Reset the error conditions
|
|
SetErrorResults( 0 );
|
|
|
|
// ------------------------------------------------------------------------
|
|
// Read in the values from the property bag.
|
|
// ------------------------------------------------------------------------
|
|
CUserInfo cUInfo( spPPPBag, this );
|
|
|
|
// ------------------------------------------------------------------------
|
|
// Use those values to do something.
|
|
// ------------------------------------------------------------------------
|
|
hr = cUInfo.CreateAccount();
|
|
if( FAILED(hr) )
|
|
{
|
|
if( !(m_dwErrCode & (ERROR_PASSWORD | ERROR_MEMBERSHIPS)) )
|
|
{
|
|
if ( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
|
|
{
|
|
SetErrorResults(ERROR_DUPE);
|
|
}
|
|
else
|
|
{
|
|
SetErrorResults(ERROR_CREATION);
|
|
}
|
|
|
|
WriteErrorResults(spPPPBag);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
hr = cUInfo.CreateMailbox();
|
|
if( FAILED(hr) )
|
|
{
|
|
SetErrorResults(ERROR_MAILBOX, bPOP3);
|
|
}
|
|
|
|
if( m_dwErrCode )
|
|
{
|
|
hr = E_FAIL;
|
|
WriteErrorResults(spPPPBag);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Revert()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CAddUser_AccntCommit::Revert()
|
|
{
|
|
NET_API_STATUS nApi;
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IADs> spUser = NULL;
|
|
CComPtr<IADsDeleteOps> spDelOps = NULL;
|
|
|
|
// Remove the entry-point in the AD if we made one.
|
|
if( m_csADName != _T("") )
|
|
{
|
|
CHECK_HR( ::ADsGetObject( m_csADName, IID_IADs, (void**)&spUser ) );
|
|
|
|
// Delete the User
|
|
hr = spUser->QueryInterface( IID_IADsDeleteOps, (void**)&spDelOps );
|
|
if( SUCCEEDED(hr) && spDelOps )
|
|
{
|
|
hr = spDelOps->DeleteObject( 0 );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ****************************************************************************
|
|
// CUserInfo
|
|
// ****************************************************************************
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CUserInfo()
|
|
//
|
|
// Constructor.
|
|
// ----------------------------------------------------------------------------
|
|
CUserInfo::CUserInfo( IPropertyPagePropertyBag* pPPPBag, CAddUser_AccntCommit* pCmt )
|
|
{
|
|
_ASSERT(pCmt);
|
|
|
|
m_pCmt = pCmt;
|
|
m_pPPPBag = pPPPBag;
|
|
m_dwAccountOptions = 0;
|
|
m_bPOP3 = FALSE;
|
|
|
|
// Get domain controller name
|
|
PDOMAIN_CONTROLLER_INFO pDCI = NULL;
|
|
DWORD dwErr = DsGetDcName( NULL, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &pDCI );
|
|
|
|
// cache the domain
|
|
if( (dwErr == NO_ERROR) && pDCI )
|
|
{
|
|
m_csDomainName = pDCI->DomainName;
|
|
NetApiBufferFree( pDCI );
|
|
pDCI = NULL;
|
|
}
|
|
|
|
// convert from '.' separated names to Dc=xxx,DC=yyy,... format
|
|
m_csFQDomainName = GetDomainPath( m_csDomainName ).c_str();
|
|
|
|
ReadBag( );
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ReadBag()
|
|
//
|
|
// Read in the values from the property bag into the member variables.
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::ReadBag()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( !m_pPPPBag ) // Make sure we have the property bag to read from.
|
|
return(E_FAIL); // If not, fail.
|
|
|
|
BOOL bRO;
|
|
|
|
// User Properties
|
|
ReadString( m_pPPPBag, PROP_USEROU_GUID_STRING, m_csUserOU, &bRO );
|
|
ReadString( m_pPPPBag, PROP_USERNAME_GUID_STRING, m_csUserName, &bRO );
|
|
ReadString( m_pPPPBag, PROP_USER_CN, m_csUserCN, &bRO );
|
|
ReadString( m_pPPPBag, PROP_PASSWD_GUID_STRING, m_csPasswd, &bRO );
|
|
ReadInt4 ( m_pPPPBag, PROP_ACCOUNT_OPT_GUID_STRING, (LONG*)&m_dwAccountOptions, &bRO );
|
|
ReadString( m_pPPPBag, PROP_USERNAME_PRE2K_GUID_STRING, m_csUserNamePre2k, &bRO );
|
|
ReadString( m_pPPPBag, PROP_FIRSTNAME_GUID_STRING, m_csFirstName, &bRO );
|
|
ReadString( m_pPPPBag, PROP_LASTNAME_GUID_STRING, m_csLastName, &bRO );
|
|
ReadString( m_pPPPBag, PROP_TELEPHONE_GUID_STRING, m_csTelephone, &bRO );
|
|
ReadString( m_pPPPBag, PROP_OFFICE_GUID_STRING, m_csOffice, &bRO );
|
|
ReadString( m_pPPPBag, PROP_DESCRIPTION_GUID_STRING, m_csDesc, &bRO );
|
|
ReadString( m_pPPPBag, PROP_LOGON_DNS, m_csLogonDns, &bRO );
|
|
|
|
// Mailbox properties
|
|
ReadBool ( m_pPPPBag, PROP_POP3_CREATE_MB_GUID_STRING, &m_bPOP3, &bRO );
|
|
ReadString( m_pPPPBag, PROP_EX_ALIAS_GUID_STRING, m_csEXAlias, &bRO );
|
|
ReadString( m_pPPPBag, PROP_EX_SERVER_GUID_STRING, m_csEXServer, &bRO );
|
|
ReadString( m_pPPPBag, PROP_EX_HOMESERVER_GUID_STRING, m_csEXHomeServer, &bRO );
|
|
ReadString( m_pPPPBag, PROP_EX_HOME_MDB_GUID_STRING, m_csEXHomeMDB, &bRO );
|
|
|
|
// Escape the User's Name
|
|
m_csUserCN = EscapeString(((LPCTSTR)m_csUserCN+3), 2);
|
|
m_csUserCN = _T("CN=") + m_csUserCN;
|
|
|
|
// Let's figure out the fullname right here and fill in the m_csFullName variable.
|
|
m_csFirstName.TrimLeft ( );
|
|
m_csFirstName.TrimRight( );
|
|
m_csLastName.TrimLeft ( );
|
|
m_csLastName.TrimRight ( );
|
|
m_csFullName.FormatMessage(IDS_FULLNAME_FORMAT_STR, (LPCTSTR)m_csFirstName, (LPCTSTR)m_csLastName);
|
|
m_csFullName.TrimLeft ( );
|
|
m_csFullName.TrimRight ( );
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CreateAccount()
|
|
//
|
|
// Makes a new user account in the Active Directory.
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::CreateAccount( )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRO = TRUE;
|
|
|
|
CComVariant vaTmpVal;
|
|
CComBSTR bstrProp;
|
|
CComPtr<IADsContainer> spADsContainer = NULL;
|
|
|
|
// Bind to the container.
|
|
CString csLdapUserOU = _T("LDAP://");
|
|
if( _tcsstr( (LPCTSTR)m_csUserOU, _T("LDAP://") ) )
|
|
{
|
|
csLdapUserOU = m_csUserOU;
|
|
}
|
|
else
|
|
{
|
|
csLdapUserOU += m_csUserOU;
|
|
}
|
|
|
|
hr = ::ADsGetObject( (LPWSTR)(LPCWSTR)csLdapUserOU, IID_IADsContainer, (VOID**) &spADsContainer );
|
|
CHECK_HR(hr);
|
|
|
|
// Create the user account.
|
|
CComPtr<IDispatch> spDisp = NULL;
|
|
bstrProp = _T("user");
|
|
CComBSTR bstrValue = (LPCWSTR)m_csUserCN;
|
|
hr = spADsContainer->Create( bstrProp, bstrValue, &spDisp );
|
|
CHECK_HR(hr);
|
|
|
|
m_pCmt->m_csADName = _T("LDAP://");
|
|
m_pCmt->m_csADName += m_csUserCN;
|
|
m_pCmt->m_csADName += _T(",");
|
|
m_pCmt->m_csADName += (LPCTSTR)csLdapUserOU+7;
|
|
|
|
// Use this new account and set it's properties (e.g. first name, home folder, etc.).
|
|
CComQIPtr<IADsUser, &IID_IADsUser> spADsUserObj(spDisp);
|
|
if( !spADsUserObj )
|
|
{
|
|
_ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
TCHAR szTmp[MAX_PATH*4] = {0};
|
|
LdapToDCName( (LPCTSTR)csLdapUserOU, szTmp, (MAX_PATH*4) );
|
|
|
|
CString csUserPrincName = m_csUserName;
|
|
csUserPrincName += _T("@");
|
|
csUserPrincName += szTmp;
|
|
|
|
// Username:
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = ((LPCWSTR)csUserPrincName);
|
|
bstrProp = _T("userPrincipalName");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
|
|
// Pre-Win2000 username:
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = ((LPCWSTR)m_csUserNamePre2k);
|
|
bstrProp = _T("sAMAccountName");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
|
|
// First name:
|
|
if( m_csFirstName.GetLength() )
|
|
{
|
|
bstrProp = (LPCWSTR)m_csFirstName;
|
|
CHECK_HR( spADsUserObj->put_FirstName( bstrProp ) );
|
|
}
|
|
|
|
// Last name:
|
|
if( m_csLastName.GetLength() )
|
|
{
|
|
bstrProp = (LPCWSTR)m_csLastName;
|
|
CHECK_HR( spADsUserObj->put_LastName( bstrProp ) );
|
|
}
|
|
|
|
if( m_csFullName.GetLength() )
|
|
{
|
|
// Full name:
|
|
bstrProp = (LPCWSTR)m_csFullName;
|
|
CHECK_HR( spADsUserObj->put_FullName( bstrProp ) );
|
|
|
|
// Display Name
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = (LPCWSTR)m_csFullName;
|
|
bstrProp = _T("displayName");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
}
|
|
|
|
// Telephone number
|
|
if( _tcslen((LPCTSTR)m_csTelephone) )
|
|
{
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = (LPCWSTR)m_csTelephone;
|
|
bstrProp = _T("telephoneNumber");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
}
|
|
|
|
// Office Location
|
|
if( _tcslen((LPCTSTR)m_csOffice) )
|
|
{
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = (LPCWSTR)m_csOffice;
|
|
bstrProp = _T("physicalDeliveryOfficeName");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
}
|
|
|
|
// Commit this information to the AD.
|
|
CHECK_HR( spADsUserObj->SetInfo() );
|
|
|
|
// Password expired?
|
|
vaTmpVal.Clear();
|
|
vaTmpVal = (m_dwAccountOptions & PASSWD_MUSTCHANGE) ? (INT) 0 : (INT) -1;
|
|
bstrProp = _T("pwdLastSet");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
|
|
// Account disabled?
|
|
vaTmpVal.Clear();
|
|
bstrProp = _T("userAccountControl");
|
|
CHECK_HR( spADsUserObj->Get( bstrProp, &vaTmpVal ) );
|
|
|
|
vaTmpVal.lVal &= ~UF_PASSWD_NOTREQD; // Make passwd required.
|
|
vaTmpVal.lVal &= ~UF_ACCOUNTDISABLE; // Do not disable the account.
|
|
bstrProp = _T("userAccountControl");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
|
|
// Set the password.
|
|
if( FAILED(SetPasswd()) )
|
|
{
|
|
m_pCmt->SetErrorResults( ERROR_PASSWORD );
|
|
|
|
vaTmpVal.Clear();
|
|
bstrProp = _T("userAccountControl");
|
|
CHECK_HR( spADsUserObj->Get( bstrProp, &vaTmpVal ) );
|
|
|
|
vaTmpVal.lVal &= ~UF_PASSWD_NOTREQD; // Make passwd required.
|
|
vaTmpVal.lVal |= UF_ACCOUNTDISABLE; // Disable the account.
|
|
bstrProp = _T("userAccountControl");
|
|
CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
|
|
|
|
// Commit this information to the AD.
|
|
CHECK_HR( spADsUserObj->SetInfo() );
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Commit this information to the AD.
|
|
CHECK_HR( spADsUserObj->SetInfo() );
|
|
|
|
// Join to Domain Users
|
|
if ( FAILED(JoinToDomainUsers()) )
|
|
{
|
|
m_pCmt->SetErrorResults( ERROR_MEMBERSHIPS );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CreateMailbox()
|
|
//
|
|
// Makes a new mailbox for the user.
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::CreateMailbox()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if( m_bPOP3 )
|
|
{
|
|
hr = CreatePOP3Mailbox();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CreatePOP3Mailbox()
|
|
//
|
|
// Makes a new (MS) POP3 mailbox for the user.
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::CreatePOP3Mailbox()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CComPtr<IP3Config> spConfig = NULL;
|
|
CComPtr<IAuthMethods> spMethods = NULL;
|
|
CComPtr<IAuthMethod> spAuth = NULL;
|
|
CComPtr<IP3Domains> spDomains = NULL;
|
|
CComPtr<IP3Domain> spDomain = NULL;
|
|
CComPtr<IP3Users> spUsers = NULL;
|
|
|
|
// Open our Pop3 Admin Interface
|
|
hr = CoCreateInstance(__uuidof(P3Config), NULL, CLSCTX_ALL, __uuidof(IP3Config), (LPVOID*)&spConfig);
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Get the Domains
|
|
hr = spConfig->get_Domains( &spDomains );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Get the first domain
|
|
CComVariant cVar;
|
|
cVar = 1;
|
|
|
|
hr = spDomains->get_Item( cVar, &spDomain );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = spDomain->get_Users( &spUsers );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = spConfig->get_Authentication( &spMethods );
|
|
}
|
|
|
|
CComVariant var;
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = spMethods->get_CurrentAuthMethod( &var );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = spMethods->get_Item( var, &spAuth );
|
|
}
|
|
|
|
CComBSTR bstrID;
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = spAuth->get_ID( &bstrID );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
CComBSTR bstrName = (LPCTSTR)m_csEXAlias;
|
|
|
|
if( _tcsicmp(bstrID, SZ_AUTH_ID_MD5_HASH) == 0 )
|
|
{
|
|
CComBSTR bstrPassword = m_csPasswd;
|
|
hr = spUsers->AddEx( bstrName, bstrPassword );
|
|
SecureZeroMemory( (LPOLESTR)bstrPassword.m_str, sizeof(OLECHAR)*bstrPassword.Length() );
|
|
}
|
|
else
|
|
{
|
|
hr = spUsers->Add( bstrName );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// SetPasswd()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::SetPasswd()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR *szPath = NULL;
|
|
TCHAR *szTok = NULL;
|
|
CString csUser = _T("LDAP://");
|
|
|
|
if ( _tcsstr((LPCTSTR)m_csUserOU, _T("LDAP://")) )
|
|
{
|
|
csUser += m_csUserCN;
|
|
csUser += _T(",");
|
|
csUser += (LPCTSTR)m_csUserOU+7;
|
|
}
|
|
else
|
|
{
|
|
csUser += m_csUserCN;
|
|
csUser += _T(",");
|
|
csUser += (LPCTSTR)m_csUserOU;
|
|
}
|
|
|
|
// Now csUser is something like "WinNT://test.microsoft.com/JohnDoe,user"
|
|
CComPtr<IADsUser> spDS = NULL;
|
|
hr = ::ADsGetObject( (LPCWSTR)csUser, IID_IADsUser, (void**)&spDS );
|
|
if ( FAILED(hr) )
|
|
return(hr);
|
|
|
|
// Set the password.
|
|
if ( _tcslen((LPCTSTR)m_csPasswd) ) // Only if there IS a passwd!
|
|
{
|
|
CComBSTR bszPasswd = (LPCWSTR) m_csPasswd;
|
|
|
|
hr = spDS->SetPassword(bszPasswd);
|
|
if ( FAILED(hr) )
|
|
return(hr);
|
|
}
|
|
|
|
// Allow change?
|
|
if ( m_dwAccountOptions & PASSWD_NOCHANGE )
|
|
{
|
|
// Get the current ACL.
|
|
CComBSTR bstrName = csUser;
|
|
PACL pDACL = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
hr = GetSDForDsObjectPath( bstrName, &pDACL, &pSD);
|
|
if( hr != S_OK ) return hr;
|
|
|
|
// build SID's for Self and World.
|
|
PSID pSidSelf = NULL;
|
|
SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
|
|
if( !AllocateAndInitializeSid(&NtAuth, 1, SECURITY_PRINCIPAL_SELF_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSelf) )
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
PSID pSidWorld;
|
|
SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
|
|
if( !AllocateAndInitializeSid(&WorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSidWorld) )
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
// initialize the entries (DENY ACE's)
|
|
EXPLICIT_ACCESS rgAccessEntry[2] = {0};
|
|
OBJECTS_AND_SID rgObjectsAndSid[2] = {0};
|
|
rgAccessEntry[0].grfAccessPermissions = ACTRL_DS_CONTROL_ACCESS;
|
|
rgAccessEntry[0].grfAccessMode = DENY_ACCESS;
|
|
rgAccessEntry[0].grfInheritance = NO_INHERITANCE;
|
|
|
|
rgAccessEntry[1].grfAccessPermissions = ACTRL_DS_CONTROL_ACCESS;
|
|
rgAccessEntry[1].grfAccessMode = DENY_ACCESS;
|
|
rgAccessEntry[1].grfInheritance = NO_INHERITANCE;
|
|
|
|
// build the trustee structs for change password
|
|
GUID UserChangePasswordGUID = { 0xab721a53, 0x1e2f, 0x11d0, { 0x98, 0x19, 0x00, 0xaa, 0x00, 0x40, 0x52, 0x9b}};
|
|
BuildTrusteeWithObjectsAndSid( &(rgAccessEntry[0].Trustee), &(rgObjectsAndSid[0]), &UserChangePasswordGUID, NULL, pSidSelf );
|
|
BuildTrusteeWithObjectsAndSid( &(rgAccessEntry[1].Trustee), &(rgObjectsAndSid[1]), &UserChangePasswordGUID, NULL, pSidWorld );
|
|
|
|
// Build the new DACL
|
|
PACL pNewDACL = NULL;
|
|
DWORD dwErr = ::SetEntriesInAcl(2, rgAccessEntry, pDACL, &pNewDACL);
|
|
if( dwErr != ERROR_SUCCESS ) return HRESULT_FROM_WIN32(dwErr);
|
|
|
|
// Set the new DACL
|
|
hr = SetDaclForDsObjectPath( bstrName, pNewDACL );
|
|
if( hr != S_OK ) return hr;
|
|
|
|
LocalFree(pSD);
|
|
}
|
|
|
|
// SetInfo only if we actually changed anything.
|
|
if ( ( _tcslen((LPCTSTR)m_csPasswd) ) || // Did we mess with the passwd?
|
|
( m_dwAccountOptions & PASSWD_NOCHANGE ) ) // Did we make it unable to change?
|
|
{
|
|
hr = spDS->SetInfo(); // If either, then set the new info.
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// JoinToGroup()
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CUserInfo::JoinToDomainUsers()
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr = S_OK;
|
|
CString csGroupName;
|
|
tstring strDomain;
|
|
tstring strUser;
|
|
|
|
// Get Domain SID
|
|
USER_MODALS_INFO_2 *pUserModalsInfo2;
|
|
NET_API_STATUS status = ::NetUserModalsGet( NULL, 2, (LPBYTE *)&pUserModalsInfo2 );
|
|
|
|
if ( (status != ERROR_SUCCESS) || (pUserModalsInfo2 == NULL) )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
PSID pSIDDomain = pUserModalsInfo2->usrmod2_domain_id;
|
|
|
|
// copy Domain RIDs
|
|
UCHAR nSubAuthorities = *::GetSidSubAuthorityCount(pSIDDomain);
|
|
|
|
DWORD adwSubAuthority[8];
|
|
for ( UCHAR index = 0; index < nSubAuthorities; index++ )
|
|
{
|
|
adwSubAuthority[index] = *::GetSidSubAuthority(pSIDDomain, index);
|
|
}
|
|
|
|
adwSubAuthority[nSubAuthorities++] = DOMAIN_GROUP_RID_USERS; // finally, append the RID we want.
|
|
|
|
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
|
|
PSID pSid = NULL;
|
|
|
|
if ( !::AllocateAndInitializeSid(&SIDAuthNT, nSubAuthorities,
|
|
adwSubAuthority[0], adwSubAuthority[1],
|
|
adwSubAuthority[2], adwSubAuthority[3],
|
|
adwSubAuthority[4], adwSubAuthority[5],
|
|
adwSubAuthority[6], adwSubAuthority[7],
|
|
&pSid) )
|
|
{
|
|
::NetApiBufferFree(pUserModalsInfo2);
|
|
return E_FAIL;
|
|
}
|
|
::NetApiBufferFree(pUserModalsInfo2);
|
|
|
|
// The builtin group names are looked up on the DC
|
|
TCHAR szDomain[MAX_PATH];
|
|
TCHAR szName[MAX_PATH];
|
|
DWORD cbDomain = MAX_PATH;
|
|
DWORD cbName = MAX_PATH;
|
|
SID_NAME_USE peUse;
|
|
|
|
if( !::LookupAccountSid( NULL, pSid, szName, &cbName, szDomain, &cbDomain, &peUse ) )
|
|
{
|
|
FreeSid(pSid);
|
|
return E_FAIL;
|
|
}
|
|
|
|
FreeSid( pSid );
|
|
|
|
// Find the Group Name
|
|
CString csTmp;
|
|
tstring strTmp = _T("LDAP://");
|
|
strTmp += m_csFQDomainName;
|
|
|
|
hr = FindADsObject(strTmp.c_str(), szName, _T("(name=%1)"), csTmp, 1, TRUE);
|
|
CHECK_HR( hr );
|
|
|
|
strTmp = _T("LDAP://");
|
|
strTmp += csTmp;
|
|
|
|
// Open the group
|
|
CComPtr<IADsGroup> spGroup = NULL;
|
|
hr = ::ADsGetObject( strTmp.c_str(), IID_IADsGroup, (void**)&spGroup );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Add the User
|
|
CComBSTR bstrName = (LPCTSTR)m_csUserOU;
|
|
hr = spGroup->Add( bstrName );
|
|
|
|
if ( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|