// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any later version. // // This software is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #include "stdafx.h" #include "boinccas.h" #include "CACreateBOINCGroups.h" #include "lsaprivs.h" #define CUSTOMACTION_NAME _T("CACreateBOINCGroups") #define CUSTOMACTION_PROGRESSTITLE _T("Validating user groups used by BOINC for secure sandboxes") ///////////////////////////////////////////////////////////////////// // // Function: // // Description: // ///////////////////////////////////////////////////////////////////// CACreateBOINCGroups::CACreateBOINCGroups(MSIHANDLE hMSIHandle) : BOINCCABase(hMSIHandle, CUSTOMACTION_NAME, CUSTOMACTION_PROGRESSTITLE) {} ///////////////////////////////////////////////////////////////////// // // Function: // // Description: // ///////////////////////////////////////////////////////////////////// CACreateBOINCGroups::~CACreateBOINCGroups() { BOINCCABase::~BOINCCABase(); } ///////////////////////////////////////////////////////////////////// // // Function: // // Description: // ///////////////////////////////////////////////////////////////////// UINT CACreateBOINCGroups::OnExecution() { NET_API_STATUS nasReturnValue; DWORD dwParameterError; UINT uiReturnValue = -1; BOOL bBOINCAdminsCreated = FALSE; BOOL bBOINCUsersCreated = FALSE; BOOL bBOINCProjectsCreated = FALSE; tstring strUserSID; tstring strUsersGroupName; tstring strBOINCMasterAccountUsername; tstring strBOINCProjectAccountUsername; tstring strEnableProtectedApplicationExecution; PSID pAdminSID = NULL; PSID pInstallingUserSID = NULL; PSID pBOINCMasterSID = NULL; PSID pBOINCProjectSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; uiReturnValue = GetProperty( _T("UserSID"), strUserSID ); if ( uiReturnValue ) return uiReturnValue; uiReturnValue = GetProperty( _T("GROUPALIAS_USERS"), strUsersGroupName ); if ( uiReturnValue ) return uiReturnValue; uiReturnValue = GetProperty( _T("BOINC_MASTER_USERNAME"), strBOINCMasterAccountUsername ); if ( uiReturnValue ) return uiReturnValue; uiReturnValue = GetProperty( _T("BOINC_PROJECT_USERNAME"), strBOINCProjectAccountUsername ); if ( uiReturnValue ) return uiReturnValue; uiReturnValue = GetProperty( _T("ENABLEPROTECTEDAPPLICATIONEXECUTION3"), strEnableProtectedApplicationExecution ); if ( uiReturnValue ) return uiReturnValue; // Create a SID for the BUILTIN\Administrators group. if(!AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID)) { LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, GetLastError(), _T("AllocateAndInitializeSid Error for BUILTIN\\Administrators") ); return ERROR_INSTALL_FAILURE; } // Create a SID for the current logged in user. if(!ConvertStringSidToSid(strUserSID.c_str(), &pInstallingUserSID)) { LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, GetLastError(), _T("ConvertStringSidToSid Error for installing user") ); return ERROR_INSTALL_FAILURE; } // Create a SID for the 'boinc_master' user account. if (_T("1") == strEnableProtectedApplicationExecution) { if(!GetAccountSid(NULL, strBOINCMasterAccountUsername.c_str(), &pBOINCMasterSID)) { LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, GetLastError(), _T("GetAccountSid Error for 'boinc_master' user account") ); return ERROR_INSTALL_FAILURE; } } // Create a SID for the 'boinc_project' user account. if (_T("1") == strEnableProtectedApplicationExecution) { if(!GetAccountSid(NULL, strBOINCProjectAccountUsername.c_str(), &pBOINCProjectSID)) { LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, GetLastError(), _T("GetAccountSid Error for 'boinc_master' user account") ); return ERROR_INSTALL_FAILURE; } } // Create the 'boinc_admins' group if needed // LOCALGROUP_INFO_1 lgrpiAdmins; lgrpiAdmins.lgrpi1_name = _T("boinc_admins"); lgrpiAdmins.lgrpi1_comment = _T("Accounts in this group can control the BOINC client."); nasReturnValue = NetLocalGroupAdd( NULL, 1, (LPBYTE)&lgrpiAdmins, &dwParameterError ); if ((NERR_Success != nasReturnValue) && (ERROR_ALIAS_EXISTS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAdd retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to create the 'boinc_admins' group.") ); return ERROR_INSTALL_FAILURE; } if (NERR_Success == nasReturnValue) { bBOINCAdminsCreated = TRUE; } // If we just created the 'boinc_admins' local group then we need to populate // it with the default accounts. LOCALGROUP_MEMBERS_INFO_0 lgrmiAdmins; lgrmiAdmins.lgrmi0_sid = pAdminSID; nasReturnValue = NetLocalGroupAddMembers( NULL, _T("boinc_admins"), 0, (LPBYTE)&lgrmiAdmins, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'boinc_admins' group (Administrator).") ); return ERROR_INSTALL_FAILURE; } lgrmiAdmins.lgrmi0_sid = pInstallingUserSID; nasReturnValue = NetLocalGroupAddMembers( NULL, _T("boinc_admins"), 0, (LPBYTE)&lgrmiAdmins, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'boinc_admins' group (Installing User).") ); return ERROR_INSTALL_FAILURE; } if (_T("1") == strEnableProtectedApplicationExecution) { lgrmiAdmins.lgrmi0_sid = pBOINCMasterSID; nasReturnValue = NetLocalGroupAddMembers( NULL, _T("boinc_admins"), 0, (LPBYTE)&lgrmiAdmins, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'boinc_admins' group (BOINC Master).") ); return ERROR_INSTALL_FAILURE; } } // Create the 'boinc_users' group if needed // LOCALGROUP_INFO_1 lgrpiUsers; lgrpiUsers.lgrpi1_name = _T("boinc_users"); lgrpiUsers.lgrpi1_comment = _T("Accounts in this group can monitor the BOINC client."); nasReturnValue = NetLocalGroupAdd( NULL, 1, (LPBYTE)&lgrpiUsers, &dwParameterError ); if ((NERR_Success != nasReturnValue) && (ERROR_ALIAS_EXISTS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAdd retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to create the 'boinc_users' group.") ); return ERROR_INSTALL_FAILURE; } if (NERR_Success == nasReturnValue) { bBOINCUsersCreated = TRUE; } // Create the 'boinc_project' group if needed // LOCALGROUP_INFO_1 lgrpiProjects; lgrpiProjects.lgrpi1_name = _T("boinc_projects"); lgrpiProjects.lgrpi1_comment = _T("Accounts in this group are used to execute boinc applications."); nasReturnValue = NetLocalGroupAdd( NULL, 1, (LPBYTE)&lgrpiProjects, &dwParameterError ); if ((NERR_Success != nasReturnValue) && (ERROR_ALIAS_EXISTS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAdd retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to create the 'boinc_projects' group.") ); return ERROR_INSTALL_FAILURE; } if (NERR_Success == nasReturnValue) { bBOINCProjectsCreated = TRUE; } // If the user has enabled protected application execution then we need to add the 'boinc_project' // account to the local group and the 'Users' local group. As an aside 'boinc_master' is also added // to the 'Users' group. if (_T("1") == strEnableProtectedApplicationExecution) { LOCALGROUP_MEMBERS_INFO_0 lgrmiMembers; lgrmiMembers.lgrmi0_sid = pBOINCProjectSID; nasReturnValue = NetLocalGroupAddMembers( NULL, _T("boinc_projects"), 0, (LPBYTE)&lgrmiMembers, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'boinc_projects' group (boinc_project).") ); return ERROR_INSTALL_FAILURE; } nasReturnValue = NetLocalGroupAddMembers( NULL, strUsersGroupName.c_str(), 0, (LPBYTE)&lgrmiMembers, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'Users' group (boinc_project).") ); return ERROR_INSTALL_FAILURE; } lgrmiMembers.lgrmi0_sid = pBOINCMasterSID; nasReturnValue = NetLocalGroupAddMembers( NULL, strUsersGroupName.c_str(), 0, (LPBYTE)&lgrmiMembers, 1 ); if ((NERR_Success != nasReturnValue) && (ERROR_MEMBER_IN_ALIAS != nasReturnValue)) { LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, nasReturnValue, _T("NetLocalGroupAddMembers retval") ); LogMessage( INSTALLMESSAGE_ERROR, NULL, NULL, NULL, nasReturnValue, _T("Failed to add user to the 'Users' group (boinc_master).") ); return ERROR_INSTALL_FAILURE; } } SetProperty( _T("BOINC_ADMINS_GROUPNAME"), _T("boinc_admins") ); SetProperty( _T("BOINC_USERS_GROUPNAME"), _T("boinc_users") ); SetProperty( _T("BOINC_PROJECTS_GROUPNAME"), _T("boinc_projects") ); if (bBOINCAdminsCreated || bBOINCUsersCreated || bBOINCProjectsCreated) { RebootWhenFinished(); } if(pAdminSID != NULL) FreeSid(pAdminSID); if(pInstallingUserSID != NULL) FreeSid(pInstallingUserSID); if(pBOINCMasterSID != NULL) FreeSid(pBOINCMasterSID); if(pBOINCProjectSID != NULL) FreeSid(pBOINCProjectSID); return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: CreateBOINCGroups // // Description: This custom action creates the three user groups that'll // be used to enfore the account based sandboxing scheme // on Windows. // ///////////////////////////////////////////////////////////////////// UINT __stdcall CreateBOINCGroups(MSIHANDLE hInstall) { UINT uiReturnValue = 0; CACreateBOINCGroups* pCA = new CACreateBOINCGroups(hInstall); uiReturnValue = pCA->Execute(); delete pCA; return uiReturnValue; }