From: VMware, Inc <> Date: Tue, 19 Oct 2010 19:11:02 +0000 (-0700) Subject: Internal branch sync. Included in this change: X-Git-Tag: 2010.10.18-313025~47 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a72cfc6701385c499da181a3a2508767cb565192;p=thirdparty%2Fopen-vm-tools.git Internal branch sync. Included in this change: . VIX: Ensure strings are valid UTF-8 when deserializing property lists. . VIX: Don't overflow buffer in list processes. . VIX: Provide the facility to set any single arbitrary attribute for a guest file. . VIX: Fix Authentication Issues. . changes in shared code that don't affect open-vm-tools functionality. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/foundryMsg/foundryMsg.c b/open-vm-tools/lib/foundryMsg/foundryMsg.c index e21632079..b17f18a6c 100644 --- a/open-vm-tools/lib/foundryMsg/foundryMsg.c +++ b/open-vm-tools/lib/foundryMsg/foundryMsg.c @@ -1734,7 +1734,8 @@ VixMsg_ParseGenericRequestMsg(const VixCommandGenericRequest *request, // IN err = VixPropertyList_Deserialize(propertyList, serializedBuffer, - request->propertyListSize); + request->propertyListSize, + VIX_PROPERTY_LIST_BAD_ENCODING_ERROR); if (VIX_OK != err) { goto abort; } @@ -2355,7 +2356,8 @@ __VMAutomationRequestParserGetPropertyList(const char *caller, err = __VMAutomationRequestParserGetData(caller, line, state, length, &data); if (VIX_OK == err) { - err = VixPropertyList_Deserialize(propList, data, length); + err = VixPropertyList_Deserialize(propList, data, length, + VIX_PROPERTY_LIST_BAD_ENCODING_ERROR); } } diff --git a/open-vm-tools/lib/foundryMsg/foundryPropertyListCommon.c b/open-vm-tools/lib/foundryMsg/foundryPropertyListCommon.c index 52561e640..e9c983800 100644 --- a/open-vm-tools/lib/foundryMsg/foundryPropertyListCommon.c +++ b/open-vm-tools/lib/foundryMsg/foundryPropertyListCommon.c @@ -31,6 +31,7 @@ #include "vm_version.h" #include "util.h" #include "str.h" +#include "unicode.h" #include "vixCommands.h" #include "vixOpenSource.h" @@ -51,10 +52,13 @@ // To be safe, we always use 8 bytes. #define PROPERTY_SIZE_POINTER 8 -static VixError VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, - const char *buffer, - size_t bufferSize, - Bool clobber); +static VixError +VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, + const char *buffer, + size_t bufferSize, + Bool clobber, + VixPropertyListBadEncodingAction action); + /* *----------------------------------------------------------------------------- @@ -197,7 +201,7 @@ VixPropertyList_Serialize(VixPropertyListImpl *propList, // IN bufferSize += headerSize; - switch(property->type) { + switch (property->type) { //////////////////////////////////////////////////////// case VIX_PROPERTYTYPE_INTEGER: bufferSize += PROPERTY_SIZE_INT32; @@ -206,7 +210,26 @@ VixPropertyList_Serialize(VixPropertyListImpl *propList, // IN //////////////////////////////////////////////////////// case VIX_PROPERTYTYPE_STRING: if (property->value.strValue) { - bufferSize += (strlen(property->value.strValue) + 1); + valueLength = strlen(property->value.strValue) + 1; + /* + * The deserialization code rejects all non-UTF-8 strings. + * There should not be any non-UTF-8 strings passing + * through our code since we should have either converted + * non-UTF-8 strings from system APIs to UTF-8, or validated + * that any client-provided strings were UTF-8. But this + * if we've missed something, this should hopefully catch the + * offending code close to the act. + */ + if (!Unicode_IsBufferValid(property->value.strValue, + valueLength, + STRING_ENCODING_UTF8)) { + Log("%s: attempted to send a non-UTF-8 string for " + "property %d.\n", + __FUNCTION__, property->propertyID); + ASSERT(0); + err = VIX_E_INVALID_UTF8_STRING; + } + bufferSize += valueLength; } else { err = VIX_E_INVALID_ARG; goto abort; @@ -274,7 +297,7 @@ VixPropertyList_Serialize(VixPropertyListImpl *propList, // IN memcpy(&(serializeBuffer[pos]), &(property->type), propertyTypeSize); pos += propertyTypeSize; - switch(property->type) { + switch (property->type) { //////////////////////////////////////////////////////// case VIX_PROPERTYTYPE_INTEGER: valueLength = PROPERTY_SIZE_INT32; @@ -372,14 +395,16 @@ abort: */ VixError -VixPropertyList_Deserialize(VixPropertyListImpl *propList, // IN - const char *buffer, // IN - size_t bufferSize) // IN +VixPropertyList_Deserialize(VixPropertyListImpl *propList, // IN + const char *buffer, // IN + size_t bufferSize, // IN + VixPropertyListBadEncodingAction action) // IN { return VixPropertyListDeserializeImpl(propList, buffer, bufferSize, - TRUE); // clobber + TRUE, // clobber + action); } // VixPropertyList_Deserialize @@ -403,12 +428,14 @@ VixPropertyList_Deserialize(VixPropertyListImpl *propList, // IN VixError VixPropertyList_DeserializeNoClobber(VixPropertyListImpl *propList, // IN const char *buffer, // IN - size_t bufferSize) // IN + size_t bufferSize, // IN + VixPropertyListBadEncodingAction action) // IN { return VixPropertyListDeserializeImpl(propList, buffer, bufferSize, - FALSE); // clobber + FALSE, // clobber + action); } // VixPropertyList_DeserializeNoClobber @@ -421,7 +448,6 @@ VixPropertyList_DeserializeNoClobber(VixPropertyListImpl *propList, // IN * * This function should be modified to deal with the case of * properties of type VIX_PROPERTYTYPE_HANDLE. - * * * Results: * VixError. @@ -433,10 +459,11 @@ VixPropertyList_DeserializeNoClobber(VixPropertyListImpl *propList, // IN */ VixError -VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, // IN - const char *buffer, // IN - size_t bufferSize, // IN - Bool clobber) // IN +VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, // IN + const char *buffer, // IN + size_t bufferSize, // IN + Bool clobber, // IN + VixPropertyListBadEncodingAction action) // IN { VixError err = VIX_OK; VixPropertyValue *property = NULL; @@ -454,6 +481,7 @@ VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, // IN size_t headerSize; VixPropertyType *propertyTypePtr; Bool allocateFailed; + Bool needToEscape; if ((NULL == propList) || (NULL == buffer)) { @@ -511,7 +539,7 @@ VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, // IN /* * Initialize the property to the received value */ - switch(*propertyTypePtr) { + switch (*propertyTypePtr) { //////////////////////////////////////////////////////// case VIX_PROPERTYTYPE_INTEGER: if (PROPERTY_SIZE_INT32 != *lengthPtr) { @@ -533,13 +561,43 @@ VixPropertyListDeserializeImpl(VixPropertyListImpl *propList, // IN err = VIX_E_INVALID_SERIALIZED_DATA; goto abort; } + + needToEscape = FALSE; + + /* + * Make sure the string is valid UTF-8 before copying it. We + * expect all strings stored in the process to be UTF-8. + */ + if (!Unicode_IsBufferValid(strPtr, *lengthPtr, + STRING_ENCODING_UTF8)) { + Log("%s: non-UTF-8 string received for property %d.\n", + __FUNCTION__, *propertyIDPtr); + switch (action) { + case VIX_PROPERTY_LIST_BAD_ENCODING_ERROR: + err = VIX_E_INVALID_UTF8_STRING; + goto abort; + case VIX_PROPERTY_LIST_BAD_ENCODING_ESCAPE: + needToEscape = TRUE; + } + + } free(property->value.strValue); - property->value.strValue = - VixMsg_StrdupClientData(strPtr, &allocateFailed); - if (allocateFailed) { - err = VIX_E_OUT_OF_MEMORY; - goto abort; + if (needToEscape) { + property->value.strValue = + Unicode_EscapeBuffer(strPtr, *lengthPtr, + STRING_ENCODING_UTF8); + if (NULL == property->value.strValue) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + } else { + property->value.strValue = + VixMsg_StrdupClientData(strPtr, &allocateFailed); + if (allocateFailed) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } } break; diff --git a/open-vm-tools/lib/include/backdoor_def.h b/open-vm-tools/lib/include/backdoor_def.h index 2338668bf..314daa9df 100644 --- a/open-vm-tools/lib/include/backdoor_def.h +++ b/open-vm-tools/lib/include/backdoor_def.h @@ -169,6 +169,12 @@ #define BDOOR_PSHARE_HINTS_VERSION 1 #define BDOOR_PSHARE_HINTS_VER(ecx) (((ecx) >> 17) & 0x7f) +/* Task applied to backdoor pshare hints */ +#define BDOOR_PSHARE_HINTS_CMD_SHARE 0 +#define BDOOR_PSHARE_HINTS_CMD_DROP 1 + +#define BDOOR_PSHARE_HINTS_CMD(ecx) (((ecx) >> 24) & 0x1) + /* Nesting control operations */ #define NESTING_CONTROL_RESTRICT_BACKDOOR 0 diff --git a/open-vm-tools/lib/include/vixCommands.h b/open-vm-tools/lib/include/vixCommands.h index ae4c5192b..79864fbaf 100644 --- a/open-vm-tools/lib/include/vixCommands.h +++ b/open-vm-tools/lib/include/vixCommands.h @@ -696,7 +696,6 @@ struct VixMsgSetGuestFileAttributesRequest { VixCommandRequestHeader header; int32 fileOptions; - int64 createTime; int64 accessTime; int64 modificationTime; int32 ownerId; diff --git a/open-vm-tools/lib/include/vixOpenSource.h b/open-vm-tools/lib/include/vixOpenSource.h index 0b06454e4..212e43daa 100644 --- a/open-vm-tools/lib/include/vixOpenSource.h +++ b/open-vm-tools/lib/include/vixOpenSource.h @@ -100,6 +100,7 @@ enum { VIX_E_OP_NOT_SUPPORTED_ON_NON_VMWARE_VM = 3038, VIX_E_VI_OP_NOT_SUPPORTED_ON_GUEST = 3048, + VIX_E_INVALID_LOGIN_CREDENTIALS = 3050, /* File Errors */ VIX_E_DIRECTORY_NOT_EMPTY = 20006, @@ -245,6 +246,33 @@ typedef struct VixPropertyListImpl } VixPropertyListImpl; +/* + * This defines what action Deserialize should take when it encounters + * a string that is not UTF-8. + */ +typedef enum VixPropertyListBadEncodingAction { + /* + * Abort the deserialization and return an error. This is the recommended + * value since it is the strictest; you don't have to think about how + * any clients or library code will handle escaped values. + * This should always be used when parsing property lists passing arguments + * to RPCs since we should be very strict in terms of actions we take + * based on arguments. + */ + VIX_PROPERTY_LIST_BAD_ENCODING_ERROR, + + /* + * Escape any non-UTF-8 characters in the string, add the result to the + * property list, and continue deserializing. This should only be used + * when there are likely to be applications generated non-ASCII values + * for the property list in question (e.g., the Tools properties sent by + * pre-i18n Tools) and the properties are more informative then + * actionable (something like the hostname of a guest, maybe). + */ + VIX_PROPERTY_LIST_BAD_ENCODING_ESCAPE, +} VixPropertyListBadEncodingAction; + + void VixPropertyList_Initialize(VixPropertyListImpl *propList); void VixPropertyList_RemoveAllWithoutHandles(VixPropertyListImpl *propList); @@ -256,11 +284,14 @@ VixError VixPropertyList_Serialize(VixPropertyListImpl *propListImpl, VixError VixPropertyList_Deserialize(VixPropertyListImpl *propListImpl, const char *buffer, - size_t bufferSize); + size_t bufferSize, + VixPropertyListBadEncodingAction action); -VixError VixPropertyList_DeserializeNoClobber(VixPropertyListImpl *propListImpl, - const char *buffer, - size_t bufferSize); +VixError +VixPropertyList_DeserializeNoClobber(VixPropertyListImpl *propListImpl, + const char *buffer, + size_t bufferSize, + VixPropertyListBadEncodingAction action); VixError VixPropertyList_GetString(struct VixPropertyListImpl *propList, int propertyID, @@ -431,6 +462,19 @@ enum { VIX_FILE_ATTRIBUTES_READONLY = 0x0008, }; +/* + * These are the propery flags for SetGuestFileAttributes request. + */ + +enum { + VIX_FILE_ATTRIBUTE_SET_ACCESS_DATE = 0x0001, + VIX_FILE_ATTRIBUTE_SET_MODIFY_DATE = 0x0002, + VIX_FILE_ATTRIBUTE_SET_READONLY = 0x0004, + VIX_FILE_ATTRIBUTE_SET_HIDDEN = 0x0008, + VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID = 0x0010, + VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID = 0x0020, + VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS = 0x0040, +}; /* diff --git a/open-vm-tools/modules/linux/shared/compat_timer.h b/open-vm-tools/modules/linux/shared/compat_timer.h index 63f43ffef..03a27971f 100644 --- a/open-vm-tools/modules/linux/shared/compat_timer.h +++ b/open-vm-tools/modules/linux/shared/compat_timer.h @@ -99,5 +99,19 @@ compat_msleep(unsigned long msecs) // IN # define compat_init_timer_deferrable(timer) init_timer(timer) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +static inline void compat_setup_timer(struct timer_list * timer, + void (*function)(unsigned long), + unsigned long data) +{ + timer->function = function; + timer->data = data; + init_timer(timer); +} +#else +# define compat_setup_timer(timer, function, data) \ + setup_timer(timer, function, data) +#endif + #endif /* __COMPAT_TIMER_H__ */ diff --git a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h index 23fa8f4d9..a438ae7af 100644 --- a/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h +++ b/open-vm-tools/modules/shared/vmxnet/vmxnet3_defs.h @@ -130,9 +130,13 @@ typedef enum { VMXNET3_CMD_GET_DID_LO, VMXNET3_CMD_GET_DID_HI, VMXNET3_CMD_GET_DEV_EXTRA_INFO, - VMXNET3_CMD_GET_CONF_INTR + VMXNET3_CMD_GET_CONF_INTR, + VMXNET3_CMD_GET_ADAPTIVE_RING_INFO } Vmxnet3_Cmd; +/* Adaptive Ring Info Flags */ +#define VMXNET3_DISABLE_ADAPTIVE_RING 1 + /* * Little Endian layout of bitfields - * Byte 0 : 7.....len.....0 diff --git a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c index 1724884f1..4f2ac370d 100644 --- a/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c +++ b/open-vm-tools/services/plugins/vix/foundryToolsDaemon.c @@ -65,6 +65,7 @@ #include "err.h" #include "hostinfo.h" #include "guest_os.h" +#include "guest_msg_def.h" #include "conf.h" #include "vixCommands.h" #include "foundryToolsDaemon.h" @@ -88,7 +89,6 @@ #include "vixTools.h" #include "vixOpenSource.h" -#define GUESTMSG_MAX_IN_SIZE (64 * 1024) /* vmx/main/guest_msg.c */ #define MAX64_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */ #if defined(linux) || defined(_WIN32) @@ -1141,7 +1141,8 @@ ToolsDaemonTcloReceiveVixCommand(RpcInData *data) // IN char *destPtr = NULL; int vixPrefixDataSize = (MAX64_DECIMAL_DIGITS * 2) + (sizeof(' ') * 2) - + sizeof('\0'); + + sizeof('\0') + + sizeof(' ') * 10; // for RPC header /* * Our temporary buffer will be the same size as what the @@ -1194,18 +1195,6 @@ abort: err = VIX_E_OUT_OF_MEMORY; } - /* - * This should never happen since tcloBuffer is pretty huge. - * But, there is no harm in being paranoid and I don't want to - * find out the buffer is too small when we are halfway through - * formatting the response. - */ - if ((32 + resultValueLength + 32) >= sizeof(tcloBuffer)) { - err = VIX_E_OUT_OF_MEMORY; - resultValueLength = 0; - } - - /* * All Foundry tools commands return results that start with a foundry error * and a guest-OS-specific error. diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c index 373f89ff3..79a80928b 100644 --- a/open-vm-tools/services/plugins/vix/vixTools.c +++ b/open-vm-tools/services/plugins/vix/vixTools.c @@ -77,6 +77,7 @@ #include "guestInfo.h" // MAX_VALUE_LEN #include "hostinfo.h" #include "guest_os.h" +#include "guest_msg_def.h" #include "conf.h" #include "vixCommands.h" #include "base64.h" @@ -115,8 +116,6 @@ #define SECONDS_BETWEEN_POLL_TEST_FINISHED 1 -#define MAX_PROCESS_LIST_RESULT_LENGTH 81920 - /* * This is used by the PRODUCT_VERSION_STRING macro. */ @@ -358,6 +357,7 @@ static VixError VixToolsGetAllEnvVarsForUser(void *userToken, char **result); static VixError VixToolsWriteVariable(VixCommandRequestHeader *requestMsg); static VixError VixToolsListProcesses(VixCommandRequestHeader *requestMsg, + size_t maxBufferSize, char **result); static VixError VixToolsListDirectory(VixCommandRequestHeader *requestMsg, @@ -396,6 +396,7 @@ static VixError VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, static VixError VixToolsValidateCredentials(VixCommandRequestHeader *requestMsg); static VixError VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, + GMainLoop *eventQueue, char **result); static VixError VixToolsReleaseCredentials(VixCommandRequestHeader *requestMsg); @@ -444,8 +445,12 @@ static int VixToolsEnvironmentTableEntryToEnvpEntry(const char *key, void *value void *clientData); static void VixToolsFreeEnvp(char **envp); + #endif +static VixError VixToolsRewriteError(uint32 opCode, + VixError origError); + /* *----------------------------------------------------------------------------- @@ -3910,6 +3915,7 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN Bool overwrite = TRUE; char *dirName = NULL; char *baseName = NULL; + int32 fileAttributeOptions = 0; #if defined(_WIN32) int fd = -1; char *tempFilePath = NULL; @@ -3933,6 +3939,7 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN } commandRequest = (VixCommandInitiateFileTransferToGuestRequest *) requestMsg; + overwrite = commandRequest->overwrite; err = VMAutomationRequestParserGetString(&parser, commandRequest->guestPathNameLength, @@ -3946,6 +3953,27 @@ VixToolsInitiateFileTransferToGuest(VixCommandRequestHeader *requestMsg) // IN goto abort; } + fileAttributeOptions = commandRequest->options; + +#if defined(_WIN32) + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS)) { + Debug("%s: Invalid attributes received for Windows Guest\n", + __FUNCTION__); + err = VIX_E_INVALID_ARG; + goto abort; + } +#else + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_HIDDEN) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_READONLY)) { + Debug("%s: Invalid attributes received for Unix Guest\n", + __FUNCTION__); + err = VIX_E_INVALID_ARG; + goto abort; + } +#endif + err = VixToolsImpersonateUser(requestMsg, &userToken); if (VIX_OK != err) { goto abort; @@ -4072,17 +4100,22 @@ abort: VixError VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN + size_t maxBufferSize, // IN char **result) // OUT { VixError err = VIX_OK; int index; - static char resultBuffer[MAX_PROCESS_LIST_RESULT_LENGTH]; + static char resultBuffer[GUESTMSG_MAX_IN_SIZE]; ProcMgr_ProcList *procList = NULL; char *destPtr; char *endDestPtr; + char *procBufPtr = NULL; + size_t procBufSize; Bool impersonatingVMWareUser = FALSE; void *userToken = NULL; + ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE); + destPtr = resultBuffer; *destPtr = 0; @@ -4098,10 +4131,9 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN goto abort; } - endDestPtr = resultBuffer + sizeof(resultBuffer); + endDestPtr = resultBuffer + maxBufferSize; for (index = 0; index < procList->procCount; index++) { - destPtr += Str_Sprintf(destPtr, - endDestPtr - destPtr, + procBufPtr = Str_Asprintf(&procBufSize, "%s%d" #if defined(_WIN32) "%d" @@ -4119,6 +4151,16 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN (NULL == procList->startTime) ? 0 : (int) procList->startTime[index]); + + if ((destPtr + procBufSize) < endDestPtr) { + destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, + "%s", procBufPtr); + } else { // out of space + free(procBufPtr); + Log("%s: proc list results too large, truncating", __FUNCTION__); + goto abort; + } + free(procBufPtr); } abort: @@ -4151,22 +4193,27 @@ abort: VixError VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN + size_t maxBufferSize, // IN char **result) // OUT { VixError err = VIX_OK; - static char resultBuffer[MAX_PROCESS_LIST_RESULT_LENGTH]; + static char resultBuffer[GUESTMSG_MAX_IN_SIZE]; ProcMgr_ProcList *procList = NULL; char *destPtr; char *endDestPtr; Bool impersonatingVMWareUser = FALSE; void *userToken = NULL; VixToolsExitedProgramState *epList; + char *procBufPtr = NULL; + size_t procBufSize; VixMsgListProcessesExRequest *listRequest; uint64 *pids = NULL; uint32 numPids; int i; int j; + ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE); + destPtr = resultBuffer; *destPtr = 0; @@ -4189,7 +4236,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN pids = (uint64 *)((char *)requestMsg + sizeof(*listRequest)); } - endDestPtr = resultBuffer + sizeof(resultBuffer); + endDestPtr = resultBuffer + maxBufferSize; /* * First check the procecess we've started via StartProgram, which @@ -4201,8 +4248,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN epList = exitedProcessList; while (epList) { if (pids[i] == epList->pid) { - destPtr += Str_Sprintf(destPtr, - endDestPtr - destPtr, + procBufPtr = Str_Asprintf(&procBufSize, "%s%"FMT64"d" "%s%d" "%d%d" @@ -4213,6 +4259,16 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN (int) epList->startTime, epList->exitCode, (int) epList->endTime); + if ((destPtr + procBufSize) < endDestPtr) { + destPtr += Str_Sprintf(destPtr, + endDestPtr - destPtr, + "%s", procBufPtr); + } else { // out of space + free(procBufPtr); + Log("%s: proc list results too large, truncating", __FUNCTION__); + goto abort; + } + free(procBufPtr); } epList = epList->next; } @@ -4220,8 +4276,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN } else { epList = exitedProcessList; while (epList) { - destPtr += Str_Sprintf(destPtr, - endDestPtr - destPtr, + procBufPtr = Str_Asprintf(&procBufSize, "%s%"FMT64"d" "%s%d" "%d%d" @@ -4232,6 +4287,16 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN (int) epList->startTime, epList->exitCode, (int) epList->endTime); + if ((destPtr + procBufSize) < endDestPtr) { + destPtr += Str_Sprintf(destPtr, + endDestPtr - destPtr, + "%s", procBufPtr); + } else { // out of space + free(procBufPtr); + Log("%s: proc list results too large, truncating", __FUNCTION__); + goto abort; + } + free(procBufPtr); epList = epList->next; } } @@ -4251,8 +4316,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN continue; } if (pids[i] == procList->procIdList[j]) { - destPtr += Str_Sprintf(destPtr, - endDestPtr - destPtr, + procBufPtr = Str_Asprintf(&procBufSize, "%s%d" "%s%d" "00" @@ -4266,6 +4330,16 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN (NULL == procList->startTime) ? 0 : (int) procList->startTime[j]); + if ((destPtr + procBufSize) < endDestPtr) { + destPtr += Str_Sprintf(destPtr, + endDestPtr - destPtr, + "%s", procBufPtr); + } else { // out of space + free(procBufPtr); + Log("%s: proc list results too large, truncating", __FUNCTION__); + goto abort; + } + free(procBufPtr); } } } @@ -4275,8 +4349,7 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN if (VixToolsFindExitedProgramState(procList->procIdList[i])) { continue; } - destPtr += Str_Sprintf(destPtr, - endDestPtr - destPtr, + procBufPtr = Str_Asprintf(&procBufSize, "%s%d" "%s%d" "00" @@ -4290,6 +4363,16 @@ VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN (NULL == procList->startTime) ? 0 : (int) procList->startTime[i]); + if ((destPtr + procBufSize) < endDestPtr) { + destPtr += Str_Sprintf(destPtr, + endDestPtr - destPtr, + "%s", procBufPtr); + } else { // out of space + free(procBufPtr); + Log("%s: proc list results too large, truncating", __FUNCTION__); + goto abort; + } + free(procBufPtr); } } @@ -4809,6 +4892,22 @@ VixToolsListFiles(VixCommandRequestHeader *requestMsg, // IN err = FoundryToolsDaemon_TranslateSystemErr(); goto abort; } + /* + * File_ListDirectory() doesn't return '.' and '..', but we want them, + * so add '.' and '..' to the list. Place them in front since that's + * a more normal location. + */ + numFiles += 2; + { + char **newFileNameList = NULL; + + newFileNameList = Util_SafeMalloc(numFiles * sizeof(char *)); + newFileNameList[0] = Unicode_Alloc(".", STRING_ENCODING_UTF8); + newFileNameList[1] = Unicode_Alloc("..", STRING_ENCODING_UTF8); + memcpy(newFileNameList + 2, fileNameList, (numFiles - 2) * sizeof(char *)); + free(fileNameList); + fileNameList = newFileNameList; + } } else { if (File_Exists(dirPathName)) { listingSingleFile = TRUE; @@ -4909,7 +5008,6 @@ VixToolsListFiles(VixCommandRequestHeader *requestMsg, // IN for (fileNum = offset + index, count = 0; count < numResults; fileNum++, count++) { - /* File_ListDirectory never returns "." or ".." */ currentFileName = fileNameList[fileNum]; @@ -5132,9 +5230,18 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN int64 accessTime; int64 modificationTime; VMAutomationRequestParser parser; + int64 tempTime; + Bool timeAttributeSpecified = FALSE; + Bool windowsAttributeSpecified = FALSE; + Bool posixAttributeSpecified = FALSE; + int32 fileAttributeOptions = 0; #ifdef _WIN32 DWORD fileAttr = 0; +#else + int ownerId = 0; + int groupId = 0; + struct stat statbuf; #endif ASSERT(NULL != requestMsg); @@ -5164,6 +5271,40 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN goto abort; } + fileAttributeOptions = setGuestFileAttributesRequest->fileOptions; + + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS)) { + posixAttributeSpecified = TRUE; + } + + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_HIDDEN) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_READONLY)) { + windowsAttributeSpecified = TRUE; + } + + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_ACCESS_DATE) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_MODIFY_DATE)) { + timeAttributeSpecified = TRUE; + } + +#if defined(_WIN32) + if (posixAttributeSpecified) { + Debug("%s: Invalid attributes received for Windows Guest\n", + __FUNCTION__); + err = VIX_E_INVALID_ARG; + goto abort; + } +#else + if (windowsAttributeSpecified) { + Debug("%s: Invalid attributes received for Unix Guest\n", + __FUNCTION__); + err = VIX_E_INVALID_ARG; + goto abort; + } +#endif + err = VixToolsImpersonateUser(requestMsg, &userToken); if (VIX_OK != err) { goto abort; @@ -5175,66 +5316,117 @@ VixToolsSetFileAttributes(VixCommandRequestHeader *requestMsg) // IN goto abort; } - /* - * User specifies the time in Unix Time Format. File_SetTimes() - * accepts times in Windows NT Format. We should convert the time - * from Unix Format to Windows NT Format. - */ - timeBuf.tv_sec = setGuestFileAttributesRequest->createTime; - timeBuf.tv_nsec = 0; - createTime = TimeUtil_UnixTimeToNtTime(timeBuf); + if (timeAttributeSpecified) { + success = File_GetTimes(filePathName, + &createTime, + &accessTime, + &modificationTime, + &tempTime); - timeBuf.tv_sec = setGuestFileAttributesRequest->accessTime; - timeBuf.tv_nsec = 0; - accessTime = TimeUtil_UnixTimeToNtTime(timeBuf); + if (!success) { + Debug("%s: Failed to get the times.\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } - timeBuf.tv_sec = setGuestFileAttributesRequest->modificationTime; - timeBuf.tv_nsec = 0; - modificationTime = TimeUtil_UnixTimeToNtTime(timeBuf); + /* + * User specifies the time in Unix Time Format. File_SetTimes() + * accepts times in Windows NT Format. We should convert the time + * from Unix Format to Windows NT Format. + */ - success = File_SetTimes(filePathName, - createTime, - accessTime, - modificationTime, - modificationTime); - if (!success) { - Debug("%s: Failed to set the times.\n", __FUNCTION__); - err = FoundryToolsDaemon_TranslateSystemErr(); - goto abort; - } + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_ACCESS_DATE ) { + timeBuf.tv_sec = setGuestFileAttributesRequest->accessTime; + timeBuf.tv_nsec = 0; + accessTime = TimeUtil_UnixTimeToNtTime(timeBuf); + } -#if defined(_WIN32) - fileAttr = Win32U_GetFileAttributes(filePathName); - if (fileAttr != INVALID_FILE_ATTRIBUTES) { - if (setGuestFileAttributesRequest->hidden) { - fileAttr |= FILE_ATTRIBUTE_HIDDEN; - } else { - fileAttr &= (~FILE_ATTRIBUTE_HIDDEN); + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_MODIFY_DATE) { + timeBuf.tv_sec = setGuestFileAttributesRequest->modificationTime; + timeBuf.tv_nsec = 0; + modificationTime = TimeUtil_UnixTimeToNtTime(timeBuf); } - if (setGuestFileAttributesRequest->readOnly) { - fileAttr |= FILE_ATTRIBUTE_READONLY; - } else { - fileAttr &= (~FILE_ATTRIBUTE_READONLY); + success = File_SetTimes(filePathName, + createTime, + accessTime, + modificationTime, + modificationTime); + if (!success) { + Debug("%s: Failed to set the times.\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; } + } +#if defined(_WIN32) + if (windowsAttributeSpecified) { + fileAttr = Win32U_GetFileAttributes(filePathName); + + if (fileAttr != INVALID_FILE_ATTRIBUTES) { + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_HIDDEN) { + if (setGuestFileAttributesRequest->hidden) { + fileAttr |= FILE_ATTRIBUTE_HIDDEN; + } else { + fileAttr &= (~FILE_ATTRIBUTE_HIDDEN); + } + } - Win32U_SetFileAttributes(filePathName, fileAttr); + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_READONLY) { + if (setGuestFileAttributesRequest->readOnly) { + fileAttr |= FILE_ATTRIBUTE_READONLY; + } else { + fileAttr &= (~FILE_ATTRIBUTE_READONLY); + } + } + + if (!Win32U_SetFileAttributes(filePathName, fileAttr)) { + Debug("%s: Failed to set the file attributes\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } + } else { + Debug("%s: Failed to get the file attributes\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } } #else - success = File_SetFilePermissions(filePathName, - setGuestFileAttributesRequest->permissions); - if (!success) { - Debug("%s: Failed to set the file permissions\n", __FUNCTION__); - err = FoundryToolsDaemon_TranslateSystemErr(); - goto abort; + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_PERMISSIONS) { + success = File_SetFilePermissions(filePathName, + setGuestFileAttributesRequest->permissions); + if (!success) { + Debug("%s: Failed to set the file permissions\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } } - if (Posix_Chown(filePathName, - setGuestFileAttributesRequest->ownerId, - setGuestFileAttributesRequest->groupId)) { - Debug("%s: Failed to set the owner/group Id\n", __FUNCTION__); - err = FoundryToolsDaemon_TranslateSystemErr(); - goto abort; + if ((fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) || + (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID)) { + + if (-1 != Posix_Stat(filePathName, &statbuf)) { + ownerId = statbuf.st_uid; + groupId = statbuf.st_gid; + } else { + Debug("%s: Posix_Stat(%s) failed with %d\n", + __FUNCTION__, filePathName, errno); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } + + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_OWNERID) { + ownerId = setGuestFileAttributesRequest->ownerId; + } + + if (fileAttributeOptions & VIX_FILE_ATTRIBUTE_SET_UNIX_GROUPID) { + groupId = setGuestFileAttributesRequest->groupId; + } + + if (Posix_Chown(filePathName, ownerId, groupId)) { + Debug("%s: Failed to set the owner/group Id\n", __FUNCTION__); + err = FoundryToolsDaemon_TranslateSystemErr(); + goto abort; + } } #endif @@ -5985,7 +6177,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN char const *obfuscatedNamePassword, // IN void **userToken) // OUT { - VixError err = VIX_E_GUEST_USER_PERMISSIONS; + VixError err = VIX_E_INVALID_LOGIN_CREDENTIALS; if (NULL != userToken) { *userToken = NULL; @@ -6000,7 +6192,6 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN AuthToken authToken; char *unobfuscatedUserName = NULL; char *unobfuscatedPassword = NULL; - char *ticketID = NULL; Bool success = FALSE; if (NULL != credentialTypeStr) { @@ -6098,35 +6289,9 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN if (VIX_USER_CREDENTIAL_TICKETED_SESSION == credentialType) { #ifdef _WIN32 - size_t ticketSize; char *username; - ticketSize = Base64_DecodedLength(obfuscatedNamePassword, - strlen(obfuscatedNamePassword)); - - /* - * Leave room for null terminator - */ - ticketID = Util_SafeMalloc(ticketSize + 1); - - if (!Base64_Decode(obfuscatedNamePassword, - ticketID, - ticketSize, - &ticketSize)) { - Debug("%s: Decode Failed\n", __FUNCTION__); - err = VIX_E_FAIL; - goto abort; - } - - ticketID[ticketSize] = '\0'; - - if (ticketSize != strlen(ticketID)) { - Debug("%s: Invalid Ticket\n", __FUNCTION__); - err = VIX_E_FAIL; - goto abort; - } - - err = VixToolsGetTokenHandleFromTicketID(ticketID, + err = VixToolsGetTokenHandleFromTicketID(obfuscatedNamePassword, &username, &authToken); @@ -6149,7 +6314,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN authToken = Auth_AuthenticateUser(unobfuscatedUserName, unobfuscatedPassword); if (NULL == authToken) { - err = VIX_E_GUEST_USER_PERMISSIONS; + err = VIX_E_INVALID_LOGIN_CREDENTIALS; goto abort; } if (NULL != userToken) { @@ -6166,7 +6331,7 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN success = ProcMgr_ImpersonateUserStart(unobfuscatedUserName, authToken); #endif if (!success) { - err = VIX_E_GUEST_USER_PERMISSIONS; + err = VIX_E_INVALID_LOGIN_CREDENTIALS; goto abort; } @@ -6175,8 +6340,6 @@ VixToolsImpersonateUserImplEx(char const *credentialTypeStr, // IN abort: free(unobfuscatedUserName); Util_ZeroFreeString(unobfuscatedPassword); - - Util_ZeroFreeString(ticketID); } #else @@ -6753,7 +6916,7 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN char **result) // OUT { VixError err = VIX_OK; - static char resultBuffer[MAX_PROCESS_LIST_RESULT_LENGTH]; + static char resultBuffer[GUESTMSG_MAX_IN_SIZE]; Bool impersonatingVMWareUser = FALSE; void *userToken = NULL; char *destPtr; @@ -6957,6 +7120,7 @@ abort: VixError VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, // IN + GMainLoop *eventQueue, // IN char **result) // OUT { VixError err; @@ -6966,7 +7130,7 @@ VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, // IN err = VIX_E_NOT_SUPPORTED; goto abort; #else - err = VixToolsAuthenticateWithSSPI(requestMsg, result); + err = VixToolsAuthenticateWithSSPI(requestMsg, eventQueue, result); if (VIX_OK != err) { Debug("%s: Failed to authenticate with SSPI with error %d\n", __FUNCTION__, err); @@ -7159,7 +7323,8 @@ VixToolsSetGuestNetworkingConfig(VixCommandRequestHeader *requestMsg) // IN VixPropertyList_Initialize(&propList); err = VixPropertyList_Deserialize(&propList, messageBody, - setGuestNetworkingConfigRequest -> bufferSize); + setGuestNetworkingConfigRequest -> bufferSize, + VIX_PROPERTY_LIST_BAD_ENCODING_ERROR); if (VIX_OK != err) { goto abort; } @@ -7735,13 +7900,17 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN //////////////////////////////////// case VIX_COMMAND_LIST_PROCESSES: - err = VixToolsListProcesses(requestMsg, &resultValue); + err = VixToolsListProcesses(requestMsg, + maxResultBufferSize, + &resultValue); // resultValue is static. Do not free it. break; //////////////////////////////////// case VIX_COMMAND_LIST_PROCESSES_EX: - err = VixToolsListProcessesEx(requestMsg, &resultValue); + err = VixToolsListProcessesEx(requestMsg, + maxResultBufferSize, + &resultValue); // resultValue is static. Do not free it. break; @@ -7934,7 +8103,7 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN //////////////////////////////////// case VIX_COMMAND_ACQUIRE_CREDENTIALS: - err = VixToolsAcquireCredentials(requestMsg, &resultValue); + err = VixToolsAcquireCredentials(requestMsg, eventQueue, &resultValue); // resultValue is static. Do not free it. break; @@ -8001,10 +8170,89 @@ abort: *deleteResultBufferResult = deleteResultValue; } + /* + * Remaps specific errors for backward compatibility purposes. + */ + err = VixToolsRewriteError(requestMsg->opCode, err); + return(err); } // VixTools_ProcessVixCommand +/* + *----------------------------------------------------------------------------- + * + * VixToolsRewriteError -- + * + * Rewrites the error if necessary. + * + * Some errors returned by tools need to be changed so + * that error code consistency with old VIX is maintained. + * + * So specific errors from specific operations are rewritten here. + * + * Results: + * VixError + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +VixError +VixToolsRewriteError(uint32 opCode, // IN + VixError origError) // IN +{ + VixError newError = origError; + + ASSERT(VIX_ERROR_CODE(origError) == origError); + + switch (opCode) { + /* + * This should include all non-VI guest operations. + */ + case VIX_COMMAND_CHECK_USER_ACCOUNT: + case VIX_COMMAND_LOGOUT_IN_GUEST: + case VIX_COMMAND_GET_TOOLS_STATE: + case VIX_COMMAND_LIST_PROCESSES: + case VIX_COMMAND_LIST_DIRECTORY: + case VIX_COMMAND_DELETE_GUEST_FILE: + case VIX_COMMAND_DELETE_GUEST_REGISTRY_KEY: + case VIX_COMMAND_DELETE_GUEST_DIRECTORY: + case VIX_COMMAND_DELETE_GUEST_EMPTY_DIRECTORY: + case VIX_COMMAND_REGISTRY_KEY_EXISTS: + case VIX_COMMAND_GUEST_FILE_EXISTS: + case VIX_COMMAND_DIRECTORY_EXISTS: + case VIX_COMMAND_READ_REGISTRY: + case VIX_COMMAND_WRITE_REGISTRY: + case VIX_COMMAND_KILL_PROCESS: + case VIX_COMMAND_CREATE_DIRECTORY: + case VIX_COMMAND_MOVE_GUEST_FILE: + case VIX_COMMAND_RUN_SCRIPT_IN_GUEST: + case VIX_COMMAND_RUN_PROGRAM: + case VIX_COMMAND_OPEN_URL: + case VIX_COMMAND_CREATE_TEMPORARY_FILE: + case VIX_COMMAND_READ_VARIABLE: + case VIX_COMMAND_WRITE_VARIABLE: + case VIX_COMMAND_GET_FILE_INFO: + case VMXI_HGFS_SEND_PACKET_COMMAND: + case VIX_COMMAND_GET_GUEST_NETWORKING_CONFIG: + case VIX_COMMAND_LIST_FILESYSTEMS: + case VIX_COMMAND_WAIT_FOR_TOOLS: + case VIX_COMMAND_CAPTURE_SCREEN: + switch (origError) { + case VIX_E_INVALID_LOGIN_CREDENTIALS: + newError = VIX_E_GUEST_USER_PERMISSIONS; + break; + } + break; + } + + return newError; +} + + /* *----------------------------------------------------------------------------- * diff --git a/open-vm-tools/services/plugins/vix/vixToolsInt.h b/open-vm-tools/services/plugins/vix/vixToolsInt.h index e592fe457..32e453fc7 100644 --- a/open-vm-tools/services/plugins/vix/vixToolsInt.h +++ b/open-vm-tools/services/plugins/vix/vixToolsInt.h @@ -29,6 +29,7 @@ #include "vmware.h" #include "vix.h" #include "vixCommands.h" +#include #define PROCESS_CREATOR_USER_TOKEN ((void *)1) @@ -85,6 +86,7 @@ void VixToolsDeinitTicketedSessionList(); VixError VixToolsAuthenticateWithSSPI(VixCommandRequestHeader *requestMsg, + GMainLoop *eventQueue, char **resultBuffer); VixError VixToolsGetTokenHandleFromTicketID(const char *ticketID,