//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation 1996-2001. // // File: cprivs.cpp // // Contents: implementation of CConfigPrivs // //---------------------------------------------------------------------------- #include "stdafx.h" #include "wsecmgr.h" #include "CPrivs.h" #include "GetUser.h" #include "AddGrp.h" #include "snapmgr.h" #include "util.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE } OBJECT_ATTRIBUTES; typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; #define InitializeObjectAttributes( p, n, a, r, s ) { \ (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) BOOL WseceditGetNameForSpecialSids( OUT PWSTR *ppszEveryone OPTIONAL, OUT PWSTR *ppszAuthUsers OPTIONAL, OUT PWSTR *ppszAdmins OPTIONAL, OUT PWSTR *ppszAdministrator OPTIONAL ); PSID WseceditpGetAccountDomainSid( ); ///////////////////////////////////////////////////////////////////////////// // CConfigPrivs dialog ///////////////////////////////////////////////////////////////////////////// CConfigPrivs::CConfigPrivs(UINT nTemplateID) : CAttribute(nTemplateID ? nTemplateID : IDD), m_fDirty(false) { //{{AFX_DATA_INIT(CConfigPrivs) //}}AFX_DATA_INIT m_pHelpIDs = (DWORD_PTR)a106HelpIDs; m_uTemplateResID = IDD; } void CConfigPrivs::DoDataExchange(CDataExchange* pDX) { CAttribute::DoDataExchange(pDX); DDX_Control(pDX, IDC_GRANTLIST, m_lbGrant); DDX_Control(pDX, IDC_REMOVE, m_btnRemove); DDX_Control(pDX, IDC_ADD, m_btnAdd); DDX_Control(pDX, IDC_TITLE, m_btnTitle); } BEGIN_MESSAGE_MAP(CConfigPrivs, CAttribute) ON_BN_CLICKED(IDC_ADD, OnAdd) ON_BN_CLICKED(IDC_REMOVE, OnRemove) ON_BN_CLICKED(IDC_CONFIGURE, OnConfigure) ON_LBN_SELCHANGE(IDC_GRANTLIST, OnSelChange) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CConfigPrivs message handlers ///////////////////////////////////////////////////////////////////////////// void CConfigPrivs::OnAdd() { CSCEAddGroup gu(this); PSCE_NAME_LIST pName = 0; if( IDD_CONFIG_PRIVS == m_uTemplateResID ) //Raid #404989 { gu.m_fCheckName = FALSE; } gu.m_dwFlags = SCE_SHOW_USERS | SCE_SHOW_LOCALGROUPS | SCE_SHOW_GLOBAL | SCE_SHOW_WELLKNOWN | SCE_SHOW_BUILTIN; if( IDD_DOMAIN_PRIVS == m_uTemplateResID ) //Raid #477428, Yanggao { gu.m_dwFlags = gu.m_dwFlags | SCE_SHOW_COMPUTER; } gu.SetModeBits(m_pSnapin->GetModeBits()); CString str; str.LoadString( IDS_ADD_USERGROUP ); gu.m_sTitle.Format( IDS_ADD_TITLE, str ); gu.m_sDescription.LoadString( IDS_ADD_USERGROUP ); CThemeContextActivator activator; if (gu.DoModal() ==IDOK ) { pName = gu.GetUsers(); UINT cstrMax = 0; //Raid #271219 LPWSTR pstrMax = NULL; UINT cstr = 0; while(pName) { if (LB_ERR == m_lbGrant.FindStringExact(-1,pName->Name)) { if( LB_ERR == m_lbGrant.AddString(pName->Name) ) { return; } m_fDirty = true; cstr = wcslen(pName->Name); if( cstr > cstrMax ) { cstrMax = cstr; pstrMax = pName->Name; } } pName = pName->Next; } SetModified(TRUE); CDC* pCDC = m_lbGrant.GetDC(); CSize strsize = pCDC->GetOutputTextExtent(pstrMax); m_lbGrant.ReleaseDC(pCDC); RECT winsize; m_lbGrant.GetWindowRect(&winsize); if( strsize.cx > winsize.right-winsize.left ) { m_lbGrant.SetHorizontalExtent(strsize.cx); } } } void CConfigPrivs::OnRemove() { int cbItems; int *pnItems; cbItems = m_lbGrant.GetSelCount(); pnItems = new int [cbItems]; if ( pnItems ) { m_lbGrant.GetSelItems(cbItems,pnItems); if (cbItems) { m_fDirty = true; SetModified(TRUE); } while(cbItems--) { m_lbGrant.DeleteString(pnItems[cbItems]); } delete[] pnItems; CWnd* pwnd = GetDlgItem(IDC_REMOVE); //Raid #466634, Yang Gao if( pwnd ) { CWnd* pPrev = pwnd->GetWindow(GW_HWNDPREV); //Raid #482112, yanggao, 10/20/2001 if(pPrev) { this->GotoDlgCtrl(pPrev); pwnd->EnableWindow(FALSE); } } } } void CConfigPrivs::OnConfigure() { CAttribute::OnConfigure(); if (m_bConfigure == m_bOriginalConfigure) { m_fDirty = false; } else { m_fDirty = true; } //Raid #466634, Yang Gao CWnd* pwnd = GetDlgItem(IDC_REMOVE); if( pwnd ) { if( m_lbGrant.GetCount() == 0 || m_lbGrant.GetSelCount() == 0 ) //Raid #475690, 476535, Yanggao { pwnd->EnableWindow(FALSE); } } } BOOL CConfigPrivs::OnApply() { if ( !m_bReadOnly ) { PSCE_PRIVILEGE_ASSIGNMENT ppa = 0; PSCE_NAME_LIST pNames = 0; CString strItem; int cItems = 0; int i = 0; UpdateData(TRUE); if(!m_bConfigure) { PSCE_PRIVILEGE_ASSIGNMENT pDelete; pDelete = GetPrivData(); // // Remove the item from the template if( pDelete && pDelete != (PSCE_PRIVILEGE_ASSIGNMENT)ULongToPtr(SCE_NO_VALUE) ) { m_pData->SetID((LONG_PTR)NULL); if (m_pData->GetSetting()) //Raid #390777 { m_pData->SetSetting((LONG_PTR)ULongToPtr(SCE_NO_VALUE)); } m_pData->SetUnits((LPTSTR)pDelete->Name); m_pData->SetStatus(SCE_STATUS_NOT_CONFIGURED); m_pData->SetBase((LONG_PTR)ULongToPtr(SCE_NO_VALUE)); m_pData->GetBaseProfile()->UpdatePrivilegeAssignedTo( TRUE, // Delete the profile. &pDelete); m_pData->GetBaseProfile()->SetDirty(AREA_PRIVILEGES); m_pData->Update(m_pSnapin); } } else if (m_fDirty) { ppa = GetPrivData(); PWSTR pszPrivName = m_pData->GetUnits(); if ( ppa ) { // // to handle configured privilege case where Units is NULL // pszPrivName = ppa->Name; } int cSpecialItems = m_lbGrant.GetCount(); DWORD dwIds = 0; CString strDenyItem; // // simulate SCE engine behavior to special case certain privileges/rights // if ( pszPrivName ) { //Prefast warning 400: Yields unexpected result in non-English locale. //Comments: It is always English locale. if ( _wcsicmp(pszPrivName, SE_INTERACTIVE_LOGON_NAME) == 0 ) { if ( cSpecialItems == 0 ) { // // logon locally right cannot be assigned to no one // dwIds = IDS_PRIV_WARNING_LOCAL_LOGON; } else { PWSTR pszAdmins = NULL; // // get the administrators group name // logon locally right must be assigned to the administrator group // if ( WseceditGetNameForSpecialSids(NULL, NULL, &pszAdmins, NULL) ) { for (i=0;i= cSpecialItems ) { // // cannot find administrators // dwIds = IDS_PRIV_WARNING_LOCAL_LOGON; } LocalFree(pszAdmins); } else { dwIds = IDS_PRIV_WARNING_ACCOUNT_TRANSLATION; } } } //Prefast warning 400: Yields unexpected result in non-English locale. //Comments: It is always English locale. else if (_wcsicmp(pszPrivName, SE_DENY_INTERACTIVE_LOGON_NAME) == 0 ) { PWSTR pszEveryone = NULL; PWSTR pszAuthUsers = NULL; PWSTR pszAdmins = NULL; PWSTR pszAdministrator=NULL; // // deny logon locally right cannot be assigned to any of the following // everyone, authenticated users, administrators, administrator // if ( WseceditGetNameForSpecialSids(&pszEveryone, &pszAuthUsers, &pszAdmins, &pszAdministrator) ) { // // make sure this check covers the free text administrator account as well // PWSTR pTemp = wcschr(pszAdministrator, L'\\'); if ( pTemp ) { pTemp++; } for (i=0;iSetWindowText(strWarning); pWarn->ShowWindow(SW_SHOW); pWarn = GetDlgItem(IDC_WARNING_ICON); if (pWarn) pWarn->ShowWindow(SW_SHOW); pWarn = GetDlgItem(IDC_ADD); //Raid 498449, yanggao if( pWarn ) { this->GotoDlgCtrl(pWarn); } } else { // // Dialog box not available in some modes such as Local Policy // AfxMessageBox(strWarning); } return FALSE; } CWnd *pWarn = GetDlgItem(IDC_WARNING); //Raid #621124, Yanggao if (pWarn) { pWarn->ShowWindow(SW_HIDE); } pWarn = GetDlgItem(IDC_WARNING_ICON); if (pWarn) { pWarn->ShowWindow(SW_HIDE); } } if ( ppa == NULL && m_pData->GetUnits() ) { if ( m_pData->GetBaseProfile()->UpdatePrivilegeAssignedTo( FALSE, &ppa, m_pData->GetUnits() ) == ERROR_SUCCESS) { m_pData->GetBaseProfile()->SetDirty(AREA_PRIVILEGES); SetPrivData(ppa); } } if ( ppa ) { PSCE_NAME_LIST pNewList=NULL; cItems = m_lbGrant.GetCount(); HRESULT hr=S_OK; if (cItems != LB_ERR && m_bConfigure) { for (i=0;iAssignedTo,SCE_STRUCT_NAME_LIST); ppa->AssignedTo = pNewList; SetPrivData(ppa); m_pData->Update(m_pSnapin); m_fDirty = false; } else { // // free the new list, failed due to memory problem // if ( pNewList ) { SceFreeMemory(pNewList,SCE_STRUCT_NAME_LIST); } } } } } return CAttribute::OnApply(); } void CConfigPrivs::OnCancel() { m_bConfigure = m_bOriginalConfigure; CAttribute::OnCancel(); } PSCE_PRIVILEGE_ASSIGNMENT CConfigPrivs::GetPrivData() { ASSERT(m_pData); if (m_pData) { return (PSCE_PRIVILEGE_ASSIGNMENT) m_pData->GetID(); } return NULL; } void CConfigPrivs::SetPrivData(PSCE_PRIVILEGE_ASSIGNMENT ppa) { ASSERT(m_pData); if (m_pData) { m_pData->SetID((LONG_PTR)ppa); if (ppa) { m_pData->SetBase((LONG_PTR)ppa->AssignedTo); } else { m_pData->SetBase(NULL); } } } BOOL CConfigPrivs::OnInitDialog() { CAttribute::OnInitDialog(); PSCE_PRIVILEGE_ASSIGNMENT ppa; PSCE_NAME_LIST pNames; UpdateData(FALSE); ::SetMapMode(::GetDC(m_lbGrant.m_hWnd), MM_TEXT); ppa = GetPrivData(); if ( ppa ) { pNames = ppa->AssignedTo; UINT cstrMax = 0; //Raid #271219 LPWSTR pstrMax = NULL; UINT cstr = 0; while(pNames) { m_lbGrant.AddString(pNames->Name); cstr = wcslen(pNames->Name); if( cstr > cstrMax ) { cstrMax = cstr; pstrMax = pNames->Name; } pNames = pNames->Next; } CDC* pCDC = m_lbGrant.GetDC(); CSize strsize = pCDC->GetOutputTextExtent(pstrMax); m_lbGrant.ReleaseDC(pCDC); RECT winsize; m_lbGrant.GetWindowRect(&winsize); if( strsize.cx > winsize.right-winsize.left ) { m_lbGrant.SetHorizontalExtent(strsize.cx); } m_bConfigure = TRUE; } else if(m_pData->GetBase() == (LONG_PTR)ULongToPtr(SCE_NO_VALUE)){ m_bConfigure = FALSE; } if (m_pData->GetSetting()) { CWnd *pWarn = GetDlgItem(IDC_WARNING); if (pWarn) { CString strWarning; strWarning.LoadString(IDS_PRIV_WARNING); pWarn->SetWindowText(strWarning); pWarn->ShowWindow(SW_SHOW); pWarn = GetDlgItem(IDC_WARNING_ICON); if (pWarn) { pWarn->ShowWindow(SW_SHOW); } } } m_bOriginalConfigure = m_bConfigure; // // Update the user controls depending on the setting. // AddUserControl(IDC_GRANTLIST); AddUserControl(IDC_ADD); AddUserControl(IDC_REMOVE); m_btnTitle.SetWindowText(m_pData->GetAttrPretty()); UpdateData(FALSE); EnableUserControls(m_bConfigure); GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE); //Raid #471511, Yanggao. // The listbox should always be enabled so that its contents may be viewed // Raid# 697665 "Local Computer Policy on a DC:Allow logon locally // properties page list box scroll bar is disabled preventing viewing of all users" // bryanwal m_lbGrant.EnableWindow (TRUE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CConfigPrivs::SetInitialValue(DWORD_PTR dw) { } BOOL WseceditGetNameForSpecialSids( OUT PWSTR *ppszEveryone OPTIONAL, OUT PWSTR *ppszAuthUsers OPTIONAL, OUT PWSTR *ppszAdmins OPTIONAL, OUT PWSTR *ppszAdministrator OPTIONAL ) /*++ Routine Description: This routine returns the localized account name for the Everyone and the Auth User SIDs Arguments: ppszEveryone - ptr to fill in (should be freed outside) ppszAuthUsers - ptr to fill in (should be freed outside) ppszAdmins - ptr to fill in for Administrators ppszAdministrator - ptr to fill in for local administrator account Return value: TRUE if succeeded else FALSE -- */ { // // buffers for the SIDs // SID Sid; DWORD dwSize = sizeof(SID); PSID pSid=NULL; BOOL bError = TRUE; // // variables for sid lookup // SID_NAME_USE tmp; DWORD dwSizeDom; PWSTR dummyBuf = NULL; if ( ppszEveryone ) { // // create the SID for "everyone" // if ( CreateWellKnownSid( WinWorldSid, NULL, &Sid, &dwSize)) { // // get the required size of the account name and domain buffer // dwSize = 0; dwSizeDom = 0; LookupAccountSid( NULL, &Sid, NULL, &dwSize, NULL, &dwSizeDom, &tmp ); *ppszEveryone = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSize + 1) * sizeof(WCHAR))); dummyBuf = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSizeDom + 1) * sizeof(WCHAR))); if ( *ppszEveryone && dummyBuf ) { // // lookup the SID to get the account name - domain name is ignored // if ( LookupAccountSid( NULL, &Sid, *ppszEveryone, &dwSize, dummyBuf, &dwSizeDom, &tmp ) ) { bError = FALSE; } } } LocalFree(dummyBuf); dummyBuf = NULL; if (bError) { LocalFree(*ppszEveryone); *ppszEveryone = NULL; return FALSE; } } // // "Authenticated Users" // if ( ppszAuthUsers ) { dwSize = sizeof(SID); bError = TRUE; // // create the SID for "authenticated users" // if ( CreateWellKnownSid( WinAuthenticatedUserSid, NULL, &Sid, &dwSize)) { // // get the required size of account name and domain buffers // dwSize = 0; dwSizeDom = 0; LookupAccountSid( NULL, &Sid, NULL, &dwSize, NULL, &dwSizeDom, &tmp ); *ppszAuthUsers = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSize + 1) * sizeof(WCHAR))); dummyBuf = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSizeDom + 1) * sizeof(WCHAR))); if ( *ppszAuthUsers && dummyBuf ) { // // lookup the SID to get account name - domain name is ignored // if ( LookupAccountSid( NULL, &Sid, *ppszAuthUsers, &dwSize, dummyBuf, &dwSizeDom, &tmp ) ) { bError = FALSE; } } } LocalFree(dummyBuf); dummyBuf = NULL; if (bError) { LocalFree(*ppszAuthUsers); *ppszAuthUsers = NULL; if ( ppszEveryone ) { LocalFree(*ppszEveryone); *ppszEveryone = NULL; } return FALSE; } } // // administrators group // if ( ppszAdmins ) { dwSize = 0; bError = TRUE; // // get the size for the well known SID of administrators group // CreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, pSid, &dwSize); if ( dwSize > 0 ) { // // alocate buffer and create the well known SID // cannot use the SID buffer because Admins SID has more than // one subauthority // pSid = (PSID)LocalAlloc(LPTR, dwSize); if ( pSid && CreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, pSid, &dwSize) ) { dwSize = 0; dwSizeDom = 0; // // get the size for account name and domain buffers // LookupAccountSid( NULL, pSid, NULL, &dwSize, NULL, &dwSizeDom, &tmp ); *ppszAdmins = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSize + 1) * sizeof(WCHAR))); dummyBuf = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSizeDom + 1) * sizeof(WCHAR))); if ( *ppszAdmins && dummyBuf ) { // // look up the name, domain name (BUILTIN) is ignored // if ( LookupAccountSid( NULL, pSid, *ppszAdmins, &dwSize, dummyBuf, &dwSizeDom, &tmp ) ) { bError = FALSE; } } } LocalFree(pSid); pSid = NULL; } LocalFree(dummyBuf); dummyBuf = NULL; if (bError) { // // anything fail will free all buffers and return FALSE // LocalFree(*ppszAdmins); *ppszAdmins = NULL; if ( ppszAuthUsers ) { LocalFree(*ppszAuthUsers); *ppszAuthUsers = NULL; } if ( ppszEveryone ) { LocalFree(*ppszEveryone); *ppszEveryone = NULL; } return FALSE; } } // // the administrator user account // if ( ppszAdministrator ) { dwSize = 0; bError = TRUE; PWSTR dummy2=NULL; // // Get Account domain SID first // PSID pDomSid = WseceditpGetAccountDomainSid(); if ( pDomSid ) { // // get the size for the administrator account (local account domain is used) // CreateWellKnownSid( WinAccountAdministratorSid, pDomSid, pSid, &dwSize); if ( dwSize > 0 ) { // // cannot use the SID buffer because administrator account SID // has more than one subauthority // pSid = (PSID)LocalAlloc(LPTR, dwSize); if ( pSid && CreateWellKnownSid( WinAccountAdministratorSid, pDomSid, pSid, &dwSize) ) { // // get size for the account name and domain buffer // dwSize = 0; dwSizeDom = 0; LookupAccountSid( NULL, pSid, NULL, &dwSize, NULL, &dwSizeDom, &tmp ); dummy2 = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSize + 1) * sizeof(WCHAR))); dummyBuf = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((dwSizeDom + 1) * sizeof(WCHAR))); if ( dummy2 && dummyBuf ) { // // lookup the account name and domain name // if ( LookupAccountSid( NULL, pSid, dummy2, &dwSize, dummyBuf, &dwSizeDom, &tmp ) ) { *ppszAdministrator = (PWSTR)LocalAlloc(LPTR, (dwSize+dwSizeDom+2)*sizeof(WCHAR)); if ( *ppszAdministrator ) { // // the name to return is a fully qualified name such as Domain\Administrator // // This is a safe usage. wcscpy(*ppszAdministrator, dummyBuf); wcscat(*ppszAdministrator, L"\\"); wcscat(*ppszAdministrator, dummy2); bError = FALSE; } } } } LocalFree(pSid); pSid = NULL; } LocalFree(dummyBuf); dummyBuf = NULL; LocalFree(dummy2); dummy2 = NULL; LocalFree(pDomSid); } if (bError) { // // anything fail will free all buffers and return FALSE // LocalFree(*ppszAdministrator); *ppszAdministrator = NULL; if ( ppszAdmins ) { LocalFree(*ppszAdmins); *ppszAdmins = NULL; } if ( ppszAuthUsers ) { LocalFree(*ppszAuthUsers); *ppszAuthUsers = NULL; } if ( ppszEveryone ) { LocalFree(*ppszEveryone); *ppszEveryone = NULL; } return FALSE; } } return TRUE; } PSID WseceditpGetAccountDomainSid( ) { NTSTATUS Status; LSA_HANDLE PolicyHandle; OBJECT_ATTRIBUTES PolicyObjectAttributes; PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL; PSID DomainSid=NULL; // // Open the policy database // InitializeObjectAttributes( &PolicyObjectAttributes, NULL, // Name 0, // Attributes NULL, // Root NULL ); // Security Descriptor Status = LsaOpenPolicy( NULL, (PLSA_OBJECT_ATTRIBUTES)&PolicyObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle ); if ( NT_SUCCESS(Status) ) { // // Query the account domain information // Status = LsaQueryInformationPolicy( PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&PolicyAccountDomainInfo ); if ( NT_SUCCESS(Status) ) { DWORD Len = GetLengthSid(PolicyAccountDomainInfo->DomainSid); DomainSid = (PSID)LocalAlloc(LPTR, Len ); if ( DomainSid ) { //This is not a safe usage. Status should be STATUS_SUCCESS for LsaQueryInformationPolicy and LsaOpenPolicy. //Status should be nonzero for CopySid. Raid #552428. Status = CopySid( Len, DomainSid, PolicyAccountDomainInfo->DomainSid ); if ( !NT_SUCCESS(Status) ) { LocalFree(DomainSid); DomainSid = NULL; } } LsaFreeMemory(PolicyAccountDomainInfo); } LsaClose( PolicyHandle ); } return(DomainSid); } void CConfigPrivs::OnSelChange() //Raid #466634, Yang Gao { CWnd* pwnd = this->GetDlgItem(IDC_REMOVE); if( pwnd ) { if( m_lbGrant.GetSelCount() == 0 //Raid #476305, yanggao, for multi select listbox. || QueryReadOnly () ) // Raid# 697665 bryanwal. Listbox must enable to // view all items, but clicking it shouldn't enable // "Remove" { if( pwnd->IsWindowEnabled() ) pwnd->EnableWindow(FALSE); } else { if( !pwnd->IsWindowEnabled() ) pwnd->EnableWindow(TRUE); } } }