diff options
Diffstat (limited to 'open-vm-tools/lib/guestApp/guestApp.c')
-rw-r--r-- | open-vm-tools/lib/guestApp/guestApp.c | 473 |
1 files changed, 456 insertions, 17 deletions
diff --git a/open-vm-tools/lib/guestApp/guestApp.c b/open-vm-tools/lib/guestApp/guestApp.c index 70e999ee..cacd56f7 100644 --- a/open-vm-tools/lib/guestApp/guestApp.c +++ b/open-vm-tools/lib/guestApp/guestApp.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 1998 VMware, Inc. All rights reserved. + * Copyright (C) 1998-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -66,6 +66,19 @@ # define GUESTAPP_TOOLS_INSTALL_PATH "/etc/vmware-tools" #endif +#if defined _WIN32 +static char *GuestAppGetOrCreateConfPath(void); +static DWORD GuestAppCreateConfPathSecInfo(PSECURITY_ATTRIBUTES *confPathSecAttrs, + PACL *confPathAcl); +static VOID GuestAppDestroyConfPathSecInfo(PSECURITY_ATTRIBUTES confPathSecAttrs, + PACL confPathAcl); +static DWORD GuestAppCreateConfPathSD(PSECURITY_DESCRIPTOR *confPathSD, + PACL *confPathAcl); +static VOID GuestAppDestroyConfPathSD(PSECURITY_DESCRIPTOR confPathSd, + PACL confPathAcl); +static DWORD GuestAppCreateConfPathAcl(PACL *newAcl); +static VOID GuestAppDestroyConfPathAcl(PACL confPathAcl); +#endif /* *----------------------------------------------------------------------------- @@ -99,7 +112,7 @@ GuestApp_GetDefaultScript(const char *confName) // IN return value; } -#ifdef _WIN32 +#if defined _WIN32 /* *------------------------------------------------------------------------------ @@ -199,7 +212,7 @@ GuestApp_GetInstallPath(void) { char *pathUtf8 = NULL; -#if defined(_WIN32) +#if defined _WIN32 size_t pathLen = 0; if (WinReg_GetSZ(HKEY_LOCAL_MACHINE, @@ -256,25 +269,451 @@ GuestApp_GetInstallPath(void) char * GuestApp_GetConfPath(void) { -#if defined(_WIN32) - char *path = W32Util_GetVmwareCommonAppDataFilePath(NULL); + static char *confPath = NULL; - if (path != NULL) { - char *tmp = Str_SafeAsprintf(NULL, "%s%c%s", path, DIRSEPC, - ProductState_GetName()); - free(path); - path = tmp; + if (confPath == NULL) { +#if defined _WIN32 + confPath = GuestAppGetOrCreateConfPath(); +#else + /* Just call into GuestApp_GetInstallPath. */ + confPath = GuestApp_GetInstallPath(); +#endif + } - if (!File_EnsureDirectory(path)) { - free(path); - path = NULL; + /* + * Return a copy of the cached confPath. + */ + return confPath ? Util_SafeStrdup(confPath) : NULL; +} + +#if defined _WIN32 + +/* + *---------------------------------------------------------------------- + * + * GuestAppGetOrCreateConfPath -- + * + * Get the path to the Tools configuration file. + * + * The return conf path is a dynamically allocated UTF-8 encoded + * string that should be freed by the caller. + * The directory will be created if it doesn't exist. + * + * However, the function will also return NULL if we fail to create + * a "VMware/VMware Tools" directory. This can occur if we're not running + * as Administrator, which VMwareUser doesn't. But I believe that + * VMwareService will always come up before VMwareUser, so by the time + * a non-root user process calls this function, the directory exists. + * + * Results: + * The path in UTF-8, or NULL on failure. + * + * Side effects: + * Allocates memory and creates the directory if it does not exist. + * + *---------------------------------------------------------------------- + */ + +static char * +GuestAppGetOrCreateConfPath(void) +{ + PSECURITY_ATTRIBUTES confPathSecAttrs = NULL; + PACL confPathAcl = NULL; + char *path; + char *tmp; + DWORD status = ERROR_SUCCESS; + + path = W32Util_GetVmwareCommonAppDataFilePath(NULL); + if (path == NULL) { + goto exit; + } + + tmp = Str_SafeAsprintf(NULL, "%s%c%s", path, DIRSEPC, ProductState_GetName()); + free(path); + path = tmp; + + if (File_Exists(path)) { + goto exit; + } + + status = GuestAppCreateConfPathSecInfo(&confPathSecAttrs, &confPathAcl); + if (ERROR_SUCCESS != status) { + Warning("%s: Error: Get security info failed %u\n", __FUNCTION__, status); + goto exit; + } + + if (!CreateDirectoryA(path, confPathSecAttrs)) { + status = GetLastError(); + if (ERROR_ALREADY_EXISTS == status) { + Debug("%s: Error: CreateDirectory path exists %u\n", __FUNCTION__, status); + status = ERROR_SUCCESS; + } else { + Warning("%s: Error: CreateDirectory failed %u\n", __FUNCTION__, status); + goto exit; } } +exit: + GuestAppDestroyConfPathSecInfo(confPathSecAttrs, confPathAcl); + + if (ERROR_SUCCESS != status) { + free(path); + path = NULL; + } + return path; -#else - /* Just call into GuestApp_GetInstallPath. */ - return GuestApp_GetInstallPath(); -#endif } + +/* + *----------------------------------------------------------------------------- + * + * GuestAppCreateConfPathSecInfo -- + * + * Creates the user access security attributes. + * + * Results: + * ERROR_SUCCESS on success or appropriate failure code. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static DWORD +GuestAppCreateConfPathSecInfo(PSECURITY_ATTRIBUTES *confPathSecAttrs, // OUT: security attrs + PACL *confPathAcl) // OUT: acl +{ + PSECURITY_ATTRIBUTES newSA = NULL; + PSECURITY_DESCRIPTOR newSD = NULL; + PACL newAcl = NULL; + DWORD status = ERROR_SUCCESS; + + Debug("%s: entered\n", __FUNCTION__); + + ASSERT(NULL != confPathSecAttrs); + ASSERT(NULL != confPathAcl); + + /* Initialize a security descriptor. */ + newSA = malloc(sizeof *newSA); + if (NULL == newSA) { + status = ERROR_NOT_ENOUGH_MEMORY; + Warning("%s: Error: malloc failed %u\n", __FUNCTION__, status); + goto exit; + } + memset(newSA, 0, sizeof *newSA); + + status = GuestAppCreateConfPathSD(&newSD, &newAcl); + if (ERROR_SUCCESS != status) { + Warning("%s: Error: SD creation failed %u\n", __FUNCTION__, status); + goto exit; + } + + newSA->nLength = sizeof *newSA; + newSA->bInheritHandle = FALSE; + newSA->lpSecurityDescriptor = newSD; + +exit: + if (ERROR_SUCCESS != status) { + GuestAppDestroyConfPathSecInfo(newSA, newAcl); + newSA = NULL; + newAcl = NULL; + } + *confPathSecAttrs = newSA; + *confPathAcl = newAcl; + return status; +} + + +/* + *----------------------------------------------------------------------------- + * + * GuestAppDestroyConfPathSecInfo -- + * + * Destroys the security attributes and ACL. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static VOID +GuestAppDestroyConfPathSecInfo(PSECURITY_ATTRIBUTES confPathSecAttrs, // IN/OUT: security attrs + PACL confPathAcl) // IN/OUT: acl +{ + if (NULL != confPathSecAttrs) { + GuestAppDestroyConfPathSD(confPathSecAttrs->lpSecurityDescriptor, + confPathAcl); + free(confPathSecAttrs); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * GuestAppCreateConfPathSD -- + * + * Creates a security descriptor for the configuration path. + * + * Results: + * ERROR_SUCCESS on success or appropriate failure code. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static DWORD +GuestAppCreateConfPathSD(PSECURITY_DESCRIPTOR *confPathSD, // OUT: security + PACL *confPathAcl) // OUT: acl +{ + DWORD status = ERROR_SUCCESS; + PACL newConfPathAcl = NULL; + PSECURITY_DESCRIPTOR newConfPathSD = NULL; + + ASSERT(NULL != confPathSD); + ASSERT(NULL != confPathAcl); + + status = GuestAppCreateConfPathAcl(&newConfPathAcl); + if (ERROR_SUCCESS != status) { + Warning("%s: Error: Get Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Initialize a security descriptor. */ + newConfPathSD = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH); + if (NULL == newConfPathSD) { + status = ERROR_NOT_ENOUGH_MEMORY; + Warning("%s: Error: malloc failed %u\n", __FUNCTION__, status); + goto exit; + } + + if (!InitializeSecurityDescriptor(newConfPathSD, SECURITY_DESCRIPTOR_REVISION)) { + status = GetLastError(); + Warning("%s: Error: InitializeSecurityDescriptor failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Add the ACL to the security descriptor. */ + if (!SetSecurityDescriptorDacl(newConfPathSD, + TRUE, + newConfPathAcl, + FALSE)) { + status = GetLastError(); + Warning("%s: Error: SetSecurityDescriptorDacl failed %u\n", __FUNCTION__, status); + goto exit; + } + +exit: + if (ERROR_SUCCESS != status) { + GuestAppDestroyConfPathSD(newConfPathSD, newConfPathAcl); + newConfPathSD = NULL; + newConfPathAcl = NULL; + } + *confPathSD = newConfPathSD; + *confPathAcl = newConfPathAcl; + return status; +} + + +/* + *----------------------------------------------------------------------------- + * + * GuestAppDestroyConfPathSD -- + * + * Destroys the security descriptor and access control list. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static VOID +GuestAppDestroyConfPathSD(PSECURITY_DESCRIPTOR confPathSd, // IN/OUT: security + PACL confPathAcl) // IN/OUT: acl +{ + free(confPathSd); + GuestAppDestroyConfPathAcl(confPathAcl); +} + + +/* + *----------------------------------------------------------------------------- + * + * GuestAppCreateConfPathAcl -- + * + * Create a new user access ACL. + * + * Results: + * ERROR_SUCCESS on success or appropriate failure code. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static DWORD +GuestAppCreateConfPathAcl(PACL *confPathAcl) // OUT: ACL +{ + PACL newAcl = NULL; + PSID systemSID = NULL; + PSID adminsGrpSID = NULL; + PSID everyoneSID = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + DWORD newAclSize; + DWORD status = ERROR_SUCCESS; + + ASSERT(NULL != confPathAcl); + + /* Create a well-known SID for the Everyone group. */ + if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &everyoneSID)) { + status = GetLastError(); + Warning("%s: Error: AllocateAndInitializeSid Error %u\n", __FUNCTION__, status); + goto exit; + } + + /* Create a well-known SID for the Administrators group. */ + if (!AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &adminsGrpSID)) { + status = GetLastError(); + Warning("%s: Error: AllocateAndInitializeSid Error %u\n", __FUNCTION__, status); + goto exit; + } + + /* Create a well-known SID for the System user. */ + if (!AllocateAndInitializeSid(&SIDAuthNT, 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &systemSID)) { + status = GetLastError(); + Warning("%s: Error: AllocateAndInitializeSid Error %u\n", __FUNCTION__, status); + goto exit; + } + + + /* + * Get the size of the new ACL. See the following link for this calculation. + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa378853(v=vs.85).aspx? + */ + newAclSize = sizeof *newAcl; + newAclSize += GetLengthSid(systemSID) + sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); + newAclSize += GetLengthSid(adminsGrpSID) + sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); + newAclSize += GetLengthSid(everyoneSID) + sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); + + /* Align newAclSize to a DWORD. */ + newAclSize = (newAclSize + (sizeof (DWORD) - 1)) & 0xfffffffc; + + /* Allocate the new ACL. */ + newAcl = malloc(newAclSize); + if (NULL == newAcl) { + status = ERROR_NOT_ENOUGH_MEMORY; + Warning("%s: Error: malloc Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Initialize the new DACL. */ + if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) { + status = GetLastError(); + Warning("%s: Error: Init Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Add the ACE to the DACL for the sid. Note: no inheritence. */ + if (!AddAccessAllowedAceEx(newAcl, + ACL_REVISION, + CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_READ | GENERIC_EXECUTE, + everyoneSID)) { + status = GetLastError(); + Warning("%s: Error: Add Everyone Ace to Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Add the ACE to the ACL for the sid. Note: no inheritence. */ + if (!AddAccessAllowedAceEx(newAcl, + ACL_REVISION, + CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + adminsGrpSID)) { + status = GetLastError(); + Warning("%s: Error: Add admins Grp Ace to Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + + /* Add the ACE to the ACL for the sid. Note: no inheritence. */ + if (!AddAccessAllowedAceEx(newAcl, + ACL_REVISION, + CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + systemSID)) { + status = GetLastError(); + Warning("%s: Error: Add system Ace to Acl failed %u\n", __FUNCTION__, status); + goto exit; + } + +exit: + /* Free the allocated SIDs. */ + if (NULL != everyoneSID) { + FreeSid(everyoneSID);; + } + + if (NULL != adminsGrpSID) { + FreeSid(adminsGrpSID); + } + + if (NULL != systemSID) { + FreeSid(systemSID); + } + + if (ERROR_SUCCESS != status) { + GuestAppDestroyConfPathAcl(newAcl); + newAcl = NULL; + } + *confPathAcl = newAcl; + + return status; +} + + +/* + *----------------------------------------------------------------------------- + * + * GuestAppDestroyConfPathAcl -- + * + * Destroys the ACL. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static VOID +GuestAppDestroyConfPathAcl(PACL confPathAcl) // IN/OUT: security +{ + free(confPathAcl); +} +#endif + |