Leaked source code of windows server 2003
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

  1. // AccntCmt.cpp : Implementation of CAddUser_AccntCommit
  2. #include "stdafx.h"
  3. #include "AU_Accnt.h"
  4. #include "AccntCmt.h"
  5. #include <dsgetdc.h>
  6. #include <lm.h>
  7. #include <lmshare.h>
  8. #include <Aclapi.h>
  9. #include <atlcom.h>
  10. // ldap/adsi includes
  11. #include <iads.h>
  12. #include <adshlp.h>
  13. #include <adsiid.h>
  14. #include <proputil.h>
  15. #include <CreateEmailName.h>
  16. #include <P3admin.h>
  17. #include <CheckUser.h>
  18. // POP3 Defines
  19. #define SZ_AUTH_ID_MD5_HASH _T("c395e20c-2236-4af7-b736-54fad07dc526")
  20. // Defines for account flags.
  21. #define PASSWD_NOCHANGE 0x01
  22. #define PASSWD_CANCHANGE 0x02
  23. #define PASSWD_MUSTCHANGE 0x04
  24. #ifndef CHECK_HR
  25. #define CHECK_HR( x ) CHECK_HR_RET( x, _hr );
  26. #define CHECK_HR_RET( x, y ) \
  27. { \
  28. HRESULT _hr = x; \
  29. if( FAILED(_hr) ) \
  30. { \
  31. _ASSERT( !_T("CHECK_HR_RET() failed. calling TRACE() with HRESULT and statement") ); \
  32. return y; \
  33. } \
  34. }
  35. #endif // CHECK_HRhr;
  36. // ****************************************************************************
  37. // CAddUser_AccntCommit
  38. // ****************************************************************************
  39. // ----------------------------------------------------------------------------
  40. // WriteErrorResults()
  41. // ----------------------------------------------------------------------------
  42. HRESULT CAddUser_AccntCommit::WriteErrorResults( IPropertyPagePropertyBag* pPPPBag )
  43. {
  44. // ------------------------------------------------------------------------
  45. // Write the the values to the property bag.
  46. // ------------------------------------------------------------------------
  47. if( FAILED(WriteInt4 ( pPPPBag, PROP_ACCNT_ERROR_CODE_GUID_STRING, m_dwErrCode, FALSE )) )
  48. {
  49. _ASSERT(FALSE);
  50. }
  51. if( FAILED(WriteString( pPPPBag, PROP_ACCNT_ERROR_STR_GUID_STRING, m_csErrStr, FALSE )) )
  52. {
  53. _ASSERT(FALSE);
  54. }
  55. return S_OK;
  56. }
  57. // ----------------------------------------------------------------------------
  58. // SetErrCode()
  59. // ----------------------------------------------------------------------------
  60. void CAddUser_AccntCommit::SetErrCode( DWORD dwCode )
  61. {
  62. m_dwErrCode |= dwCode;
  63. return;
  64. }
  65. // ----------------------------------------------------------------------------
  66. // SetErrorResults()
  67. // ----------------------------------------------------------------------------
  68. HRESULT CAddUser_AccntCommit::SetErrorResults( DWORD dwErrType, BOOL bPOP3 /* = FALSE */ )
  69. {
  70. SetErrCode(dwErrType);
  71. CString csTemp;
  72. switch( dwErrType )
  73. {
  74. case ERROR_CREATION:
  75. case ERROR_PROPERTIES:
  76. {
  77. m_csErrStr.LoadString(IDS_ERROR_CREATING_USER);
  78. break;
  79. }
  80. case ERROR_MAILBOX:
  81. {
  82. csTemp.LoadString( IDS_ERROR_POP3MAILBOX);
  83. m_csErrStr += csTemp;
  84. break;
  85. }
  86. case ERROR_PASSWORD:
  87. {
  88. csTemp.LoadString(IDS_ERROR_PASSWORD);
  89. m_csErrStr += csTemp;
  90. break;
  91. }
  92. case ERROR_DUPE:
  93. {
  94. csTemp.LoadString(IDS_ERROR_DUPLICATE);
  95. m_csErrStr += csTemp;
  96. break;
  97. }
  98. case ERROR_MEMBERSHIPS:
  99. {
  100. csTemp.LoadString(IDS_ERROR_MEMBERSHIP);
  101. m_csErrStr += csTemp;
  102. break;
  103. }
  104. default :
  105. {
  106. m_dwErrCode = 0;
  107. m_csErrStr = _T("");
  108. break;
  109. }
  110. }
  111. return S_OK;
  112. }
  113. // ----------------------------------------------------------------------------
  114. // Commit()
  115. // ----------------------------------------------------------------------------
  116. HRESULT CAddUser_AccntCommit::Commit( IDispatch* pdispPPPBag )
  117. {
  118. HRESULT hr = S_OK;
  119. HRESULT hrAdmin = IsUserInGroup( DOMAIN_ALIAS_RID_ADMINS );
  120. if( hrAdmin != S_OK )
  121. {
  122. return E_ACCESSDENIED;
  123. }
  124. CComPtr<IPropertyPagePropertyBag> spPPPBag = NULL;
  125. hr = pdispPPPBag->QueryInterface( __uuidof(IPropertyPagePropertyBag), (void**)&spPPPBag );
  126. if ( !spPPPBag )
  127. return hr;
  128. BOOL bRO = FALSE;
  129. BOOL bPOP3 = FALSE;
  130. ReadBool( spPPPBag, PROP_POP3_CREATE_MB_GUID_STRING, &bPOP3, &bRO );
  131. // Reset the error conditions
  132. SetErrorResults( 0 );
  133. // ------------------------------------------------------------------------
  134. // Read in the values from the property bag.
  135. // ------------------------------------------------------------------------
  136. CUserInfo cUInfo( spPPPBag, this );
  137. // ------------------------------------------------------------------------
  138. // Use those values to do something.
  139. // ------------------------------------------------------------------------
  140. hr = cUInfo.CreateAccount();
  141. if( FAILED(hr) )
  142. {
  143. if( !(m_dwErrCode & (ERROR_PASSWORD | ERROR_MEMBERSHIPS)) )
  144. {
  145. if ( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
  146. {
  147. SetErrorResults(ERROR_DUPE);
  148. }
  149. else
  150. {
  151. SetErrorResults(ERROR_CREATION);
  152. }
  153. WriteErrorResults(spPPPBag);
  154. return E_FAIL;
  155. }
  156. }
  157. hr = cUInfo.CreateMailbox();
  158. if( FAILED(hr) )
  159. {
  160. SetErrorResults(ERROR_MAILBOX, bPOP3);
  161. }
  162. if( m_dwErrCode )
  163. {
  164. hr = E_FAIL;
  165. WriteErrorResults(spPPPBag);
  166. }
  167. return hr;
  168. }
  169. // ----------------------------------------------------------------------------
  170. // Revert()
  171. // ----------------------------------------------------------------------------
  172. HRESULT CAddUser_AccntCommit::Revert()
  173. {
  174. NET_API_STATUS nApi;
  175. HRESULT hr = S_OK;
  176. CComPtr<IADs> spUser = NULL;
  177. CComPtr<IADsDeleteOps> spDelOps = NULL;
  178. // Remove the entry-point in the AD if we made one.
  179. if( m_csADName != _T("") )
  180. {
  181. CHECK_HR( ::ADsGetObject( m_csADName, IID_IADs, (void**)&spUser ) );
  182. // Delete the User
  183. hr = spUser->QueryInterface( IID_IADsDeleteOps, (void**)&spDelOps );
  184. if( SUCCEEDED(hr) && spDelOps )
  185. {
  186. hr = spDelOps->DeleteObject( 0 );
  187. }
  188. }
  189. return hr;
  190. }
  191. // ****************************************************************************
  192. // CUserInfo
  193. // ****************************************************************************
  194. // ----------------------------------------------------------------------------
  195. // CUserInfo()
  196. //
  197. // Constructor.
  198. // ----------------------------------------------------------------------------
  199. CUserInfo::CUserInfo( IPropertyPagePropertyBag* pPPPBag, CAddUser_AccntCommit* pCmt )
  200. {
  201. _ASSERT(pCmt);
  202. m_pCmt = pCmt;
  203. m_pPPPBag = pPPPBag;
  204. m_dwAccountOptions = 0;
  205. m_bPOP3 = FALSE;
  206. // Get domain controller name
  207. PDOMAIN_CONTROLLER_INFO pDCI = NULL;
  208. DWORD dwErr = DsGetDcName( NULL, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED, &pDCI );
  209. // cache the domain
  210. if( (dwErr == NO_ERROR) && pDCI )
  211. {
  212. m_csDomainName = pDCI->DomainName;
  213. NetApiBufferFree( pDCI );
  214. pDCI = NULL;
  215. }
  216. // convert from '.' separated names to Dc=xxx,DC=yyy,... format
  217. m_csFQDomainName = GetDomainPath( m_csDomainName ).c_str();
  218. ReadBag( );
  219. }
  220. // ----------------------------------------------------------------------------
  221. // ReadBag()
  222. //
  223. // Read in the values from the property bag into the member variables.
  224. // ----------------------------------------------------------------------------
  225. HRESULT CUserInfo::ReadBag()
  226. {
  227. HRESULT hr = S_OK;
  228. if ( !m_pPPPBag ) // Make sure we have the property bag to read from.
  229. return(E_FAIL); // If not, fail.
  230. BOOL bRO;
  231. // User Properties
  232. ReadString( m_pPPPBag, PROP_USEROU_GUID_STRING, m_csUserOU, &bRO );
  233. ReadString( m_pPPPBag, PROP_USERNAME_GUID_STRING, m_csUserName, &bRO );
  234. ReadString( m_pPPPBag, PROP_USER_CN, m_csUserCN, &bRO );
  235. ReadString( m_pPPPBag, PROP_PASSWD_GUID_STRING, m_csPasswd, &bRO );
  236. ReadInt4 ( m_pPPPBag, PROP_ACCOUNT_OPT_GUID_STRING, (LONG*)&m_dwAccountOptions, &bRO );
  237. ReadString( m_pPPPBag, PROP_USERNAME_PRE2K_GUID_STRING, m_csUserNamePre2k, &bRO );
  238. ReadString( m_pPPPBag, PROP_FIRSTNAME_GUID_STRING, m_csFirstName, &bRO );
  239. ReadString( m_pPPPBag, PROP_LASTNAME_GUID_STRING, m_csLastName, &bRO );
  240. ReadString( m_pPPPBag, PROP_TELEPHONE_GUID_STRING, m_csTelephone, &bRO );
  241. ReadString( m_pPPPBag, PROP_OFFICE_GUID_STRING, m_csOffice, &bRO );
  242. ReadString( m_pPPPBag, PROP_DESCRIPTION_GUID_STRING, m_csDesc, &bRO );
  243. ReadString( m_pPPPBag, PROP_LOGON_DNS, m_csLogonDns, &bRO );
  244. // Mailbox properties
  245. ReadBool ( m_pPPPBag, PROP_POP3_CREATE_MB_GUID_STRING, &m_bPOP3, &bRO );
  246. ReadString( m_pPPPBag, PROP_EX_ALIAS_GUID_STRING, m_csEXAlias, &bRO );
  247. ReadString( m_pPPPBag, PROP_EX_SERVER_GUID_STRING, m_csEXServer, &bRO );
  248. ReadString( m_pPPPBag, PROP_EX_HOMESERVER_GUID_STRING, m_csEXHomeServer, &bRO );
  249. ReadString( m_pPPPBag, PROP_EX_HOME_MDB_GUID_STRING, m_csEXHomeMDB, &bRO );
  250. // Escape the User's Name
  251. m_csUserCN = EscapeString(((LPCTSTR)m_csUserCN+3), 2);
  252. m_csUserCN = _T("CN=") + m_csUserCN;
  253. // Let's figure out the fullname right here and fill in the m_csFullName variable.
  254. m_csFirstName.TrimLeft ( );
  255. m_csFirstName.TrimRight( );
  256. m_csLastName.TrimLeft ( );
  257. m_csLastName.TrimRight ( );
  258. m_csFullName.FormatMessage(IDS_FULLNAME_FORMAT_STR, (LPCTSTR)m_csFirstName, (LPCTSTR)m_csLastName);
  259. m_csFullName.TrimLeft ( );
  260. m_csFullName.TrimRight ( );
  261. return(hr);
  262. }
  263. // ----------------------------------------------------------------------------
  264. // CreateAccount()
  265. //
  266. // Makes a new user account in the Active Directory.
  267. // ----------------------------------------------------------------------------
  268. HRESULT CUserInfo::CreateAccount( )
  269. {
  270. HRESULT hr = S_OK;
  271. BOOL bRO = TRUE;
  272. CComVariant vaTmpVal;
  273. CComBSTR bstrProp;
  274. CComPtr<IADsContainer> spADsContainer = NULL;
  275. // Bind to the container.
  276. CString csLdapUserOU = _T("LDAP://");
  277. if( _tcsstr( (LPCTSTR)m_csUserOU, _T("LDAP://") ) )
  278. {
  279. csLdapUserOU = m_csUserOU;
  280. }
  281. else
  282. {
  283. csLdapUserOU += m_csUserOU;
  284. }
  285. hr = ::ADsGetObject( (LPWSTR)(LPCWSTR)csLdapUserOU, IID_IADsContainer, (VOID**) &spADsContainer );
  286. CHECK_HR(hr);
  287. // Create the user account.
  288. CComPtr<IDispatch> spDisp = NULL;
  289. bstrProp = _T("user");
  290. CComBSTR bstrValue = (LPCWSTR)m_csUserCN;
  291. hr = spADsContainer->Create( bstrProp, bstrValue, &spDisp );
  292. CHECK_HR(hr);
  293. m_pCmt->m_csADName = _T("LDAP://");
  294. m_pCmt->m_csADName += m_csUserCN;
  295. m_pCmt->m_csADName += _T(",");
  296. m_pCmt->m_csADName += (LPCTSTR)csLdapUserOU+7;
  297. // Use this new account and set it's properties (e.g. first name, home folder, etc.).
  298. CComQIPtr<IADsUser, &IID_IADsUser> spADsUserObj(spDisp);
  299. if( !spADsUserObj )
  300. {
  301. _ASSERT(FALSE);
  302. return E_FAIL;
  303. }
  304. TCHAR szTmp[MAX_PATH*4] = {0};
  305. LdapToDCName( (LPCTSTR)csLdapUserOU, szTmp, (MAX_PATH*4) );
  306. CString csUserPrincName = m_csUserName;
  307. csUserPrincName += _T("@");
  308. csUserPrincName += szTmp;
  309. // Username:
  310. vaTmpVal.Clear();
  311. vaTmpVal = ((LPCWSTR)csUserPrincName);
  312. bstrProp = _T("userPrincipalName");
  313. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  314. // Pre-Win2000 username:
  315. vaTmpVal.Clear();
  316. vaTmpVal = ((LPCWSTR)m_csUserNamePre2k);
  317. bstrProp = _T("sAMAccountName");
  318. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  319. // First name:
  320. if( m_csFirstName.GetLength() )
  321. {
  322. bstrProp = (LPCWSTR)m_csFirstName;
  323. CHECK_HR( spADsUserObj->put_FirstName( bstrProp ) );
  324. }
  325. // Last name:
  326. if( m_csLastName.GetLength() )
  327. {
  328. bstrProp = (LPCWSTR)m_csLastName;
  329. CHECK_HR( spADsUserObj->put_LastName( bstrProp ) );
  330. }
  331. if( m_csFullName.GetLength() )
  332. {
  333. // Full name:
  334. bstrProp = (LPCWSTR)m_csFullName;
  335. CHECK_HR( spADsUserObj->put_FullName( bstrProp ) );
  336. // Display Name
  337. vaTmpVal.Clear();
  338. vaTmpVal = (LPCWSTR)m_csFullName;
  339. bstrProp = _T("displayName");
  340. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  341. }
  342. // Telephone number
  343. if( _tcslen((LPCTSTR)m_csTelephone) )
  344. {
  345. vaTmpVal.Clear();
  346. vaTmpVal = (LPCWSTR)m_csTelephone;
  347. bstrProp = _T("telephoneNumber");
  348. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  349. }
  350. // Office Location
  351. if( _tcslen((LPCTSTR)m_csOffice) )
  352. {
  353. vaTmpVal.Clear();
  354. vaTmpVal = (LPCWSTR)m_csOffice;
  355. bstrProp = _T("physicalDeliveryOfficeName");
  356. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  357. }
  358. // Commit this information to the AD.
  359. CHECK_HR( spADsUserObj->SetInfo() );
  360. // Password expired?
  361. vaTmpVal.Clear();
  362. vaTmpVal = (m_dwAccountOptions & PASSWD_MUSTCHANGE) ? (INT) 0 : (INT) -1;
  363. bstrProp = _T("pwdLastSet");
  364. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  365. // Account disabled?
  366. vaTmpVal.Clear();
  367. bstrProp = _T("userAccountControl");
  368. CHECK_HR( spADsUserObj->Get( bstrProp, &vaTmpVal ) );
  369. vaTmpVal.lVal &= ~UF_PASSWD_NOTREQD; // Make passwd required.
  370. vaTmpVal.lVal &= ~UF_ACCOUNTDISABLE; // Do not disable the account.
  371. bstrProp = _T("userAccountControl");
  372. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  373. // Set the password.
  374. if( FAILED(SetPasswd()) )
  375. {
  376. m_pCmt->SetErrorResults( ERROR_PASSWORD );
  377. vaTmpVal.Clear();
  378. bstrProp = _T("userAccountControl");
  379. CHECK_HR( spADsUserObj->Get( bstrProp, &vaTmpVal ) );
  380. vaTmpVal.lVal &= ~UF_PASSWD_NOTREQD; // Make passwd required.
  381. vaTmpVal.lVal |= UF_ACCOUNTDISABLE; // Disable the account.
  382. bstrProp = _T("userAccountControl");
  383. CHECK_HR( spADsUserObj->Put( bstrProp, vaTmpVal ) );
  384. // Commit this information to the AD.
  385. CHECK_HR( spADsUserObj->SetInfo() );
  386. return E_FAIL;
  387. }
  388. // Commit this information to the AD.
  389. CHECK_HR( spADsUserObj->SetInfo() );
  390. // Join to Domain Users
  391. if ( FAILED(JoinToDomainUsers()) )
  392. {
  393. m_pCmt->SetErrorResults( ERROR_MEMBERSHIPS );
  394. return E_FAIL;
  395. }
  396. return S_OK;
  397. }
  398. // ----------------------------------------------------------------------------
  399. // CreateMailbox()
  400. //
  401. // Makes a new mailbox for the user.
  402. // ----------------------------------------------------------------------------
  403. HRESULT CUserInfo::CreateMailbox()
  404. {
  405. HRESULT hr = S_OK;
  406. if( m_bPOP3 )
  407. {
  408. hr = CreatePOP3Mailbox();
  409. }
  410. return hr;
  411. }
  412. // ----------------------------------------------------------------------------
  413. // CreatePOP3Mailbox()
  414. //
  415. // Makes a new (MS) POP3 mailbox for the user.
  416. // ----------------------------------------------------------------------------
  417. HRESULT CUserInfo::CreatePOP3Mailbox()
  418. {
  419. HRESULT hr = S_OK;
  420. CComPtr<IP3Config> spConfig = NULL;
  421. CComPtr<IAuthMethods> spMethods = NULL;
  422. CComPtr<IAuthMethod> spAuth = NULL;
  423. CComPtr<IP3Domains> spDomains = NULL;
  424. CComPtr<IP3Domain> spDomain = NULL;
  425. CComPtr<IP3Users> spUsers = NULL;
  426. // Open our Pop3 Admin Interface
  427. hr = CoCreateInstance(__uuidof(P3Config), NULL, CLSCTX_ALL, __uuidof(IP3Config), (LPVOID*)&spConfig);
  428. if( SUCCEEDED(hr) )
  429. {
  430. // Get the Domains
  431. hr = spConfig->get_Domains( &spDomains );
  432. }
  433. if( SUCCEEDED(hr) )
  434. {
  435. // Get the first domain
  436. CComVariant cVar;
  437. cVar = 1;
  438. hr = spDomains->get_Item( cVar, &spDomain );
  439. }
  440. if( SUCCEEDED(hr) )
  441. {
  442. hr = spDomain->get_Users( &spUsers );
  443. }
  444. if ( SUCCEEDED(hr) )
  445. {
  446. hr = spConfig->get_Authentication( &spMethods );
  447. }
  448. CComVariant var;
  449. if ( SUCCEEDED(hr) )
  450. {
  451. hr = spMethods->get_CurrentAuthMethod( &var );
  452. }
  453. if ( SUCCEEDED(hr) )
  454. {
  455. hr = spMethods->get_Item( var, &spAuth );
  456. }
  457. CComBSTR bstrID;
  458. if( SUCCEEDED(hr) )
  459. {
  460. hr = spAuth->get_ID( &bstrID );
  461. }
  462. if( SUCCEEDED(hr) )
  463. {
  464. CComBSTR bstrName = (LPCTSTR)m_csEXAlias;
  465. if( _tcsicmp(bstrID, SZ_AUTH_ID_MD5_HASH) == 0 )
  466. {
  467. CComBSTR bstrPassword = m_csPasswd;
  468. hr = spUsers->AddEx( bstrName, bstrPassword );
  469. SecureZeroMemory( (LPOLESTR)bstrPassword.m_str, sizeof(OLECHAR)*bstrPassword.Length() );
  470. }
  471. else
  472. {
  473. hr = spUsers->Add( bstrName );
  474. }
  475. }
  476. return hr;
  477. }
  478. // ----------------------------------------------------------------------------
  479. // SetPasswd()
  480. // ----------------------------------------------------------------------------
  481. HRESULT CUserInfo::SetPasswd()
  482. {
  483. HRESULT hr = S_OK;
  484. TCHAR *szPath = NULL;
  485. TCHAR *szTok = NULL;
  486. CString csUser = _T("LDAP://");
  487. if ( _tcsstr((LPCTSTR)m_csUserOU, _T("LDAP://")) )
  488. {
  489. csUser += m_csUserCN;
  490. csUser += _T(",");
  491. csUser += (LPCTSTR)m_csUserOU+7;
  492. }
  493. else
  494. {
  495. csUser += m_csUserCN;
  496. csUser += _T(",");
  497. csUser += (LPCTSTR)m_csUserOU;
  498. }
  499. // Now csUser is something like "WinNT://test.microsoft.com/JohnDoe,user"
  500. CComPtr<IADsUser> spDS = NULL;
  501. hr = ::ADsGetObject( (LPCWSTR)csUser, IID_IADsUser, (void**)&spDS );
  502. if ( FAILED(hr) )
  503. return(hr);
  504. // Set the password.
  505. if ( _tcslen((LPCTSTR)m_csPasswd) ) // Only if there IS a passwd!
  506. {
  507. CComBSTR bszPasswd = (LPCWSTR) m_csPasswd;
  508. hr = spDS->SetPassword(bszPasswd);
  509. if ( FAILED(hr) )
  510. return(hr);
  511. }
  512. // Allow change?
  513. if ( m_dwAccountOptions & PASSWD_NOCHANGE )
  514. {
  515. // Get the current ACL.
  516. CComBSTR bstrName = csUser;
  517. PACL pDACL = NULL;
  518. PSECURITY_DESCRIPTOR pSD = NULL;
  519. hr = GetSDForDsObjectPath( bstrName, &pDACL, &pSD);
  520. if( hr != S_OK ) return hr;
  521. // build SID's for Self and World.
  522. PSID pSidSelf = NULL;
  523. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  524. if( !AllocateAndInitializeSid(&NtAuth, 1, SECURITY_PRINCIPAL_SELF_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSelf) )
  525. {
  526. return HRESULT_FROM_WIN32(GetLastError());
  527. }
  528. PSID pSidWorld;
  529. SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
  530. if( !AllocateAndInitializeSid(&WorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSidWorld) )
  531. {
  532. return HRESULT_FROM_WIN32(GetLastError());
  533. }
  534. // initialize the entries (DENY ACE's)
  535. EXPLICIT_ACCESS rgAccessEntry[2] = {0};
  536. OBJECTS_AND_SID rgObjectsAndSid[2] = {0};
  537. rgAccessEntry[0].grfAccessPermissions = ACTRL_DS_CONTROL_ACCESS;
  538. rgAccessEntry[0].grfAccessMode = DENY_ACCESS;
  539. rgAccessEntry[0].grfInheritance = NO_INHERITANCE;
  540. rgAccessEntry[1].grfAccessPermissions = ACTRL_DS_CONTROL_ACCESS;
  541. rgAccessEntry[1].grfAccessMode = DENY_ACCESS;
  542. rgAccessEntry[1].grfInheritance = NO_INHERITANCE;
  543. // build the trustee structs for change password
  544. GUID UserChangePasswordGUID = { 0xab721a53, 0x1e2f, 0x11d0, { 0x98, 0x19, 0x00, 0xaa, 0x00, 0x40, 0x52, 0x9b}};
  545. BuildTrusteeWithObjectsAndSid( &(rgAccessEntry[0].Trustee), &(rgObjectsAndSid[0]), &UserChangePasswordGUID, NULL, pSidSelf );
  546. BuildTrusteeWithObjectsAndSid( &(rgAccessEntry[1].Trustee), &(rgObjectsAndSid[1]), &UserChangePasswordGUID, NULL, pSidWorld );
  547. // Build the new DACL
  548. PACL pNewDACL = NULL;
  549. DWORD dwErr = ::SetEntriesInAcl(2, rgAccessEntry, pDACL, &pNewDACL);
  550. if( dwErr != ERROR_SUCCESS ) return HRESULT_FROM_WIN32(dwErr);
  551. // Set the new DACL
  552. hr = SetDaclForDsObjectPath( bstrName, pNewDACL );
  553. if( hr != S_OK ) return hr;
  554. LocalFree(pSD);
  555. }
  556. // SetInfo only if we actually changed anything.
  557. if ( ( _tcslen((LPCTSTR)m_csPasswd) ) || // Did we mess with the passwd?
  558. ( m_dwAccountOptions & PASSWD_NOCHANGE ) ) // Did we make it unable to change?
  559. {
  560. hr = spDS->SetInfo(); // If either, then set the new info.
  561. }
  562. return(hr);
  563. }
  564. // ----------------------------------------------------------------------------
  565. // JoinToGroup()
  566. // ----------------------------------------------------------------------------
  567. HRESULT CUserInfo::JoinToDomainUsers()
  568. {
  569. USES_CONVERSION;
  570. HRESULT hr = S_OK;
  571. CString csGroupName;
  572. tstring strDomain;
  573. tstring strUser;
  574. // Get Domain SID
  575. USER_MODALS_INFO_2 *pUserModalsInfo2;
  576. NET_API_STATUS status = ::NetUserModalsGet( NULL, 2, (LPBYTE *)&pUserModalsInfo2 );
  577. if ( (status != ERROR_SUCCESS) || (pUserModalsInfo2 == NULL) )
  578. {
  579. return E_FAIL;
  580. }
  581. PSID pSIDDomain = pUserModalsInfo2->usrmod2_domain_id;
  582. // copy Domain RIDs
  583. UCHAR nSubAuthorities = *::GetSidSubAuthorityCount(pSIDDomain);
  584. DWORD adwSubAuthority[8];
  585. for ( UCHAR index = 0; index < nSubAuthorities; index++ )
  586. {
  587. adwSubAuthority[index] = *::GetSidSubAuthority(pSIDDomain, index);
  588. }
  589. adwSubAuthority[nSubAuthorities++] = DOMAIN_GROUP_RID_USERS; // finally, append the RID we want.
  590. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  591. PSID pSid = NULL;
  592. if ( !::AllocateAndInitializeSid(&SIDAuthNT, nSubAuthorities,
  593. adwSubAuthority[0], adwSubAuthority[1],
  594. adwSubAuthority[2], adwSubAuthority[3],
  595. adwSubAuthority[4], adwSubAuthority[5],
  596. adwSubAuthority[6], adwSubAuthority[7],
  597. &pSid) )
  598. {
  599. ::NetApiBufferFree(pUserModalsInfo2);
  600. return E_FAIL;
  601. }
  602. ::NetApiBufferFree(pUserModalsInfo2);
  603. // The builtin group names are looked up on the DC
  604. TCHAR szDomain[MAX_PATH];
  605. TCHAR szName[MAX_PATH];
  606. DWORD cbDomain = MAX_PATH;
  607. DWORD cbName = MAX_PATH;
  608. SID_NAME_USE peUse;
  609. if( !::LookupAccountSid( NULL, pSid, szName, &cbName, szDomain, &cbDomain, &peUse ) )
  610. {
  611. FreeSid(pSid);
  612. return E_FAIL;
  613. }
  614. FreeSid( pSid );
  615. // Find the Group Name
  616. CString csTmp;
  617. tstring strTmp = _T("LDAP://");
  618. strTmp += m_csFQDomainName;
  619. hr = FindADsObject(strTmp.c_str(), szName, _T("(name=%1)"), csTmp, 1, TRUE);
  620. CHECK_HR( hr );
  621. strTmp = _T("LDAP://");
  622. strTmp += csTmp;
  623. // Open the group
  624. CComPtr<IADsGroup> spGroup = NULL;
  625. hr = ::ADsGetObject( strTmp.c_str(), IID_IADsGroup, (void**)&spGroup );
  626. if( SUCCEEDED(hr) )
  627. {
  628. // Add the User
  629. CComBSTR bstrName = (LPCTSTR)m_csUserOU;
  630. hr = spGroup->Add( bstrName );
  631. if ( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
  632. {
  633. hr = S_FALSE;
  634. }
  635. }
  636. return hr;
  637. }