1
/*********************************************************
2
* Copyright (C) 2007 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
20
* foreignVMToolsDaemon.c --
22
* This implements the Vix tools using a socket to connect to the tools
23
* from a client. This also assumes there is no VMX process, so the
24
* tools takes commands directly from the client over the socket.
27
* Client ---socket---> VMX ---backdoor---> Tools
30
* Client ---socket---> Tools
32
* So, this code performs operations on behalf of the VMX and the tools.
33
* The tools functions are all implemented by the vixTools library, which
34
* is the same code that runs in the VMware tools. This module then handles
35
* socket communication and does functions that would otherwise be done by
50
#include <sys/types.h>
52
#include <sys/socket.h>
54
#include <netinet/in.h>
55
#include <netinet/tcp.h>
56
#include <arpa/inet.h>
58
#if defined(__FreeBSD__) || defined(sun) || defined(__APPLE__)
61
#include <linux/unistd.h>
66
#include "vm_version.h"
69
#include "eventManager.h"
79
#include "hgfsServer.h"
84
#include "vixOpenSource.h"
85
#include "syncEvent.h"
86
#include "foundryThreads.h"
87
#include "vixCommands.h"
88
#include "foreignVMToolsDaemon.h"
93
VixLockType globalLock;
94
static struct FoundryWorkerThread *selectThread;
95
static DblLnkLst_Links *gEventQueue;
97
ForeignVMToolsConnection *activeConnectionList = NULL;
98
ForeignVMToolsCommand *globalCommandList = NULL;
100
static struct GuestApp_Dict *configDictionary = NULL;
102
static Bool ForeignToolsIsCommandAlive(ForeignVMToolsCommand *asyncCommand);
104
static ForeignVMToolsCommand *ForeignToolsGetActiveCommand(const char *name);
106
static void ForeignToolsSendRunProgramResponse(const char *requestName,
112
static VixError ForeignToolsGetUserCredentialForGuest(ForeignVMToolsConnection *connectionState,
113
ForeignVMToolsCommand *commandState);
115
static VixError ForeignToolsGetProperties(ForeignVMToolsCommand *asyncCommand,
116
VixMsgTrivialRequest *requestMsg);
118
static VixError ForeignToolsSetProperties(ForeignVMToolsCommand *asyncCommand,
119
VixMsgSetVMStateRequest *requestMsg);
121
static VixError ForeignToolsGetToolsState(ForeignVMToolsCommand *asyncCommand,
122
VixMsgTrivialRequest *requestMsg);
126
*-----------------------------------------------------------------------------
128
* ForeignTools_Initialize --
130
* Start a worker thread.
133
* FoundryWorkerThread *
137
*-----------------------------------------------------------------------------
141
ForeignTools_Initialize(GuestApp_Dict *configDictionaryParam, // IN
142
DblLnkLst_Links *eventQueue) // IN
144
VixError err = VIX_OK;
147
MessageStub_RegisterTransport();
148
gEventQueue = eventQueue;
151
* Initialize the limited global state that protects us when
152
* client applications explicitly pump events.
154
err = VIX_INIT_LOCK(&globalLock);
160
if (NULL == configDictionaryParam) {
164
configDictionary = configDictionaryParam;
166
VixTools_SetConsoleUserPolicy(TRUE); // allowConsoleUserOpsParam
167
VixTools_SetRunProgramCallback(ForeignToolsSendRunProgramResponse, NULL);
169
success = ForeignTools_InitializeNetworking();
175
* Start the worker threads that will pump poll.
177
selectThread = FoundryThreads_StartThread(ForeignToolsSelectLoop, NULL);
178
if (NULL == selectThread) {
186
} // ForeignTools_Initialize
190
*-----------------------------------------------------------------------------
192
* ForeignTools_Shutdown --
194
* Shutdown a thread and destroys its thread state.
201
*-----------------------------------------------------------------------------
205
ForeignTools_Shutdown(void)
208
* Tell the select thread to exit and wait for it to stop.
210
selectThread->stopThread = TRUE;
211
ForeignToolsWakeSelectThread();
212
if (NULL != selectThread) {
213
FoundryThreads_StopThread(selectThread);
218
* Close every connection.
220
VIX_ENTER_LOCK(&globalLock);
221
while (NULL != activeConnectionList) {
222
ForeignToolsCloseConnection(activeConnectionList, SHUTDOWN_FOR_SYSTEM_SHUTDOWN);
224
VIX_LEAVE_LOCK(&globalLock);
227
* Shut down the work queue.
229
VIX_DELETE_LOCK(&globalLock);
230
} // ForeignTools_Shutdown
234
*----------------------------------------------------------------------------
236
* ForeignToolsIsCommandAlive --
238
* Returns TRUE if ForeignVMToolsCommand is still in the list of
239
* active commands. Otherwise, return FALSE.
246
*----------------------------------------------------------------------------
250
ForeignToolsIsCommandAlive(ForeignVMToolsCommand *asyncCommand) // IN
252
ForeignVMToolsCommand *command;
253
ForeignVMToolsCommand *nextCommand;
254
Bool isAlive = FALSE;
256
if (NULL == asyncCommand) {
260
VIX_ENTER_LOCK(&globalLock);
262
command = globalCommandList;
263
while (NULL != command) {
264
nextCommand = command->next;
265
if (command == asyncCommand) {
269
command = nextCommand;
272
VIX_LEAVE_LOCK(&globalLock);
276
} // ForeignToolsIsCommandAlive
280
*-----------------------------------------------------------------------------
282
* ForeignToolsDiscardCommand --
284
* Record that we are executing an async command.
292
*-----------------------------------------------------------------------------
296
ForeignToolsDiscardCommand(ForeignVMToolsCommand *command) // IN
298
ForeignVMToolsCommand *targetCommand;
299
ForeignVMToolsCommand *prevCommand;
301
if ((NULL == command) || (NULL == command->connection)) {
305
VIX_ENTER_LOCK(&globalLock);
307
targetCommand = globalCommandList;
309
while (NULL != targetCommand) {
310
if (targetCommand == command) {
313
prevCommand = targetCommand;
314
targetCommand = targetCommand->next;
318
* If the command is not in the active list, then somebody else
319
* already freed it. Do not delete it again.
321
if (NULL == targetCommand) {
325
if (NULL != prevCommand) {
326
prevCommand->next = targetCommand->next;
328
globalCommandList = targetCommand->next;
331
free(command->responseBody);
332
free(command->guestUserNamePassword);
333
free(command->obfuscatedGuestUserNamePassword);
337
VIX_LEAVE_LOCK(&globalLock);
338
} // ForeignToolsDiscardCommand
342
*-----------------------------------------------------------------------------
344
* ForeignToolsGetActiveCommand --
346
* This gets the named active state.
349
* The named active state.
354
*-----------------------------------------------------------------------------
357
ForeignVMToolsCommand *
358
ForeignToolsGetActiveCommand(const char *name) // IN
360
ForeignVMToolsCommand *command = NULL;
363
* Look for the test that corresponds to this name.
365
VIX_ENTER_LOCK(&globalLock);
367
command = globalCommandList;
368
while (NULL != command) {
369
if (0 == Str_Strcasecmp(name, command->asyncOpName)) {
373
command = command->next;
376
VIX_LEAVE_LOCK(&globalLock);
379
} // ForeignToolsGetActiveCommand
384
*----------------------------------------------------------------------------
386
* ForeignToolsSendRunProgramResponse --
394
*----------------------------------------------------------------------------
398
ForeignToolsSendRunProgramResponse(const char *requestName, // IN
399
VixError resultErr, // IN
402
void *clientData) // IN
404
VixError err = VIX_OK;
405
int additionalError = 0;
406
ForeignVMToolsCommand *asyncCommand = NULL;
407
VmTimeType programStopTime;
408
VmTimeType deltaTime = 0;
409
VixMsgRunProgramResponse responseMessage;
411
Hostinfo_GetTimeOfDay(&programStopTime);
413
asyncCommand = ForeignToolsGetActiveCommand(requestName);
414
if (NULL == asyncCommand) {
418
* If all we wanted to do was start the program, then we are
421
if (asyncCommand->runProgramOptions & VIX_RUNPROGRAM_RETURN_IMMEDIATELY) {
428
* Find how long the program was running. Convert to seconds,
429
* and report the result in VMDB.
431
deltaTime = programStopTime - asyncCommand->programStartTime;
432
deltaTime = deltaTime / 1000000;
434
responseMessage.exitCode = exitCode;
435
responseMessage.deltaTime = deltaTime;
436
responseMessage.pid = pid;
437
responseMessage.stdOutLength = 0;
438
responseMessage.stdErrLength = 0;
440
ForeignToolsSendResponseUsingTotalMessage(asyncCommand->connection,
441
&(asyncCommand->requestHeader),
442
sizeof responseMessage,
446
VIX_RESPONSE_EXTENDED_RESULT_V1);
447
ForeignToolsDiscardCommand(asyncCommand);
448
} // ForeignToolsSendRunProgramResponse
452
*-----------------------------------------------------------------------------
454
* ForeignToolsGetUserCredentialForGuest --
456
* Get the credentials we will pass into the guest.
457
* These may be passed in with the original command request, or else we
458
* may use some default values.
460
* This also does limited checking, mainly to see if any credentials are
461
* even provided. It does NOT check to see if a user/name password is valid,
462
* or if a particular user is authorized for some operation. That will
463
* be done later in the guest when we actually execute each operation.
465
* This leaves the actual credentials for this command packaged in
466
* commandState->obfuscatedGuestUserNamePassword
474
*-----------------------------------------------------------------------------
478
ForeignToolsGetUserCredentialForGuest(ForeignVMToolsConnection *connectionState, // IN
479
ForeignVMToolsCommand *commandState) // IN
481
VixError err = VIX_OK;
482
//CryptoError cryptoErr = CRYPTO_ERROR_SUCCESS;
484
char *guestUserName = NULL;
485
char *guestPassword = NULL;
486
char *namePasswordMessage = NULL;
488
char *encryptedNamePassword = NULL;
489
size_t encryptedNamePasswordLength = 0;
490
char *decryptedBuffer = NULL;
491
size_t decryptedBufferLength = 0;
492
VixCommandNamePassword *guestUserNamePassword;
493
VixCommandNamePassword newUserNamePassword;
494
size_t newCredentialsLength;
495
size_t newMessageLength;
496
char *newNamePasswordBuffer;
497
//CryptoKeyedHash *keyedHash;
500
* If there was an optional userName and password sent, then parse it now.
502
if (VIX_USER_CREDENTIAL_NAME_PASSWORD == commandState->requestHeader.userCredentialType) {
503
if (commandState->requestHeader.commonHeader.credentialLength <= 0) {
504
err = VIX_E_INVALID_MESSAGE_HEADER;
508
namePasswordMessage = connectionState->completeRequest
509
+ commandState->requestHeader.commonHeader.headerLength
510
+ commandState->requestHeader.commonHeader.bodyLength;
511
endCredential = namePasswordMessage
512
+ commandState->requestHeader.commonHeader.credentialLength;
514
* Make sure this is a valid NULL-terminated C string.
516
if (*(endCredential - 1)) {
517
err = VIX_E_INVALID_MESSAGE_HEADER;
521
success = Base64_EasyDecode(namePasswordMessage,
522
(uint8 **) &encryptedNamePassword,
523
&encryptedNamePasswordLength);
525
err = VIX_E_INVALID_MESSAGE_HEADER;
530
cryptoErr = CryptoKeyedHash_FromString(CryptoKeyedHashName_HMAC_SHA_1,
532
if (CryptoError_IsFailure(cryptoErr)) {
533
err = Vix_TranslateCryptoError(cryptoErr);
537
cryptoErr = CryptoKey_DecryptWithMAC(connectionState->sessionKey,
539
(uint8 *) encryptedNamePassword,
540
encryptedNamePasswordLength,
541
(uint8 **) &decryptedBuffer,
542
&decryptedBufferLength);
543
if (CryptoError_IsFailure(cryptoErr)) {
544
err = Vix_TranslateCryptoError(cryptoErr);
548
decryptedBuffer = encryptedNamePassword;
549
decryptedBufferLength = encryptedNamePasswordLength;
553
* Get the name/password fields from the credential data structure.
555
guestUserNamePassword = (VixCommandNamePassword *) decryptedBuffer;
556
guestUserName = (char *) guestUserNamePassword;
557
guestUserName += sizeof(VixCommandNamePassword);
558
guestPassword = guestUserName;
559
guestPassword += guestUserNamePassword->nameLength + 1;
562
* If the client sent a valid userName/password, then this is OK.
563
* Send it on to the tools and they will check permissions.
564
* Allow an empty password string, that may be valid for some accounts.
566
if ((NULL == guestUserName) || !(guestUserName[0])) {
567
err = VIX_E_GUEST_USER_PERMISSIONS;
571
commandState->obfuscatedCredentialType = commandState->requestHeader.userCredentialType;
572
/////////////////////////////////////////////////////////////////////////////
573
} else if ((VIX_USER_CREDENTIAL_ANONYMOUS == commandState->requestHeader.userCredentialType)
574
|| (VIX_USER_CREDENTIAL_NONE == commandState->requestHeader.userCredentialType)) {
575
err = VIX_E_MISSING_ANON_GUEST_ACCOUNT;
577
/////////////////////////////////////////////////////////////////////////////
578
} else if (VIX_USER_CREDENTIAL_ROOT == commandState->requestHeader.userCredentialType) {
579
err = VIX_E_ROOT_GUEST_OPERATIONS_PROHIBITED;
581
/////////////////////////////////////////////////////////////////////////////
582
} else if (VIX_USER_CREDENTIAL_CONSOLE_USER == commandState->requestHeader.userCredentialType) {
583
//<> For debug only. I need this until I package the tools as
584
// an NT service. Otherwise, I cannot run a program.
585
//<><>err = VIX_E_CONSOLE_GUEST_OPERATIONS_PROHIBITED;
588
err = VIX_E_UNRECOGNIZED_COMMAND;
593
* Now, package the name/password to be sent to the guest.
595
commandState->obfuscatedGuestUserNamePassword
596
= VixMsg_ObfuscateNamePassword(guestUserName, guestPassword);
598
newCredentialsLength = sizeof(VixCommandNamePassword)
599
+ strlen(commandState->obfuscatedGuestUserNamePassword) + 1;
601
newMessageLength = commandState->requestHeader.commonHeader.totalMessageLength
602
- commandState->requestHeader.commonHeader.credentialLength
603
+ newCredentialsLength;
605
connectionState->completeRequest = Util_SafeRealloc(connectionState->completeRequest,
607
if (NULL != guestUserName) {
608
newUserNamePassword.nameLength = strlen(guestUserName);
610
newUserNamePassword.nameLength = 0;
612
if (NULL != guestPassword) {
613
newUserNamePassword.passwordLength = strlen(guestPassword);
615
newUserNamePassword.passwordLength = 0;
617
newNamePasswordBuffer = connectionState->completeRequest
618
+ commandState->requestHeader.commonHeader.headerLength
619
+ commandState->requestHeader.commonHeader.bodyLength;
621
memcpy(newNamePasswordBuffer,
622
&newUserNamePassword,
623
sizeof(newUserNamePassword));
624
newNamePasswordBuffer += sizeof(newUserNamePassword);
625
memcpy(newNamePasswordBuffer,
626
commandState->obfuscatedGuestUserNamePassword,
627
strlen(commandState->obfuscatedGuestUserNamePassword) + 1);
629
commandState->requestHeader.commonHeader.totalMessageLength = newMessageLength;
630
commandState->requestHeader.commonHeader.credentialLength = newCredentialsLength;
632
connectionState->requestHeader.commonHeader.totalMessageLength = newMessageLength;
633
connectionState->requestHeader.commonHeader.credentialLength = newCredentialsLength;
637
free(encryptedNamePassword);
639
Crypto_Free(decryptedBuffer, decryptedBufferLength);
643
} // ForeignToolsGetUserCredentialForGuest
647
*-----------------------------------------------------------------------------
649
* ForeignToolsGetProperties --
657
*-----------------------------------------------------------------------------
661
ForeignToolsGetProperties(ForeignVMToolsCommand *asyncCommand, // IN
662
VixMsgTrivialRequest *requestMsg) // IN
664
VixError err = VIX_OK;
665
VixPropertyListImpl propList;
666
char *serializedBufferBody = NULL;
667
size_t serializedBufferLength = 0;
668
char *responseMessage = NULL;
669
size_t responseMessageLength = 0;
671
int guestOSFamily = GUEST_OS_FAMILY_ANY;
673
guestOSID = 0; // GuestOS_GetOSID(NULL);
676
VixPropertyList_Initialize(&propList);
678
err = VixPropertyList_SetInteger(&propList,
679
VIX_PROPERTY_VM_TOOLS_STATE,
680
VIX_TOOLSSTATE_RUNNING);
684
err = VixPropertyList_SetString(&propList,
685
VIX_PROPERTY_VMX_VERSION,
690
err = VixPropertyList_SetString(&propList,
691
VIX_PROPERTY_FOREIGN_VM_TOOLS_VERSION,
692
VIX_FOREIGN_VM_TOOLS_VMX_VERSION_STRING);
696
err = VixPropertyList_SetString(&propList,
697
VIX_PROPERTY_VMX_PRODUCT_NAME,
702
err = VixPropertyList_SetInteger(&propList,
703
VIX_PROPERTY_VMX_VIX_FEATURES,
704
VIX_TOOLSFEATURE_SUPPORT_GET_HANDLE_STATE);
710
* *****************************************
711
* Now, fill in default values for the tools.
712
* Later, if the tools are running, they will have a chance to
713
* provide correct values.
715
err = VixPropertyList_SetString(&propList,
716
VIX_PROPERTY_GUEST_TOOLS_PRODUCT_NAM,
721
err = VixPropertyList_SetString(&propList,
722
VIX_PROPERTY_GUEST_TOOLS_VERSION,
727
err = VixPropertyList_SetInteger(&propList,
728
VIX_PROPERTY_GUEST_TOOLS_API_OPTIONS,
733
err = VixPropertyList_SetInteger(&propList,
734
VIX_PROPERTY_GUEST_OS_FAMILY,
740
err = VixPropertyList_SetString(&propList,
741
VIX_PROPERTY_GUEST_NAME,
746
err = VixPropertyList_SetString(&propList,
747
VIX_PROPERTY_GUEST_POWER_OFF_SCRIPT,
752
err = VixPropertyList_SetString(&propList,
753
VIX_PROPERTY_GUEST_POWER_ON_SCRIPT,
758
err = VixPropertyList_SetString(&propList,
759
VIX_PROPERTY_GUEST_SUSPEND_SCRIPT,
764
err = VixPropertyList_SetString(&propList,
765
VIX_PROPERTY_GUEST_RESUME_SCRIPT,
772
* Serialize the property list to buffer
774
err = VixPropertyList_Serialize(&propList,
776
&serializedBufferLength,
777
&serializedBufferBody);
782
responseMessageLength = sizeof(VixMsgGetVMStateResponse)
783
+ serializedBufferLength;
784
responseMessage = Util_SafeMalloc(responseMessageLength);
785
memcpy(responseMessage + sizeof(VixMsgGetVMStateResponse),
786
serializedBufferBody,
787
serializedBufferLength);
788
((VixMsgGetVMStateResponse *) responseMessage)->bufferSize = serializedBufferLength;
790
ForeignToolsSendResponseUsingTotalMessage(asyncCommand->connection,
791
&(asyncCommand->requestHeader),
792
responseMessageLength,
795
0, // additionalError,
797
ForeignToolsDiscardCommand(asyncCommand);
800
* ForeignToolsSendResponseUsingTotalMessage owns responseMessage now,
801
* and it will deallocate it.
803
responseMessage = NULL;
806
free(responseMessage);
807
free(serializedBufferBody);
808
VixPropertyList_RemoveAllWithoutHandles(&propList);
811
} // ForeignToolsGetProperties
815
*-----------------------------------------------------------------------------
817
* ForeignToolsSetProperties --
825
*-----------------------------------------------------------------------------
829
ForeignToolsSetProperties(ForeignVMToolsCommand *asyncCommand, // IN
830
VixMsgSetVMStateRequest *requestMsg) // IN
832
VixError err = VIX_OK;
833
VixPropertyListImpl propList;
834
size_t serializedBufferLength = 0;
835
char *serializedBuffer = NULL;
840
if ((NULL == asyncCommand)
841
|| (NULL == requestMsg)
842
|| (0 > requestMsg->bufferSize)) {
843
err = VIX_E_INVALID_ARG;
847
serializedBufferLength = requestMsg->bufferSize;
848
serializedBuffer = ((char*)requestMsg + sizeof(*requestMsg));
851
* Create a temporary property list and deserialize the buffer into.
853
err = VixPropertyList_Deserialize(&propList,
855
serializedBufferLength);
862
* Change any VMX properties here.
866
VixPropertyList_RemoveAllWithoutHandles(&propList);
869
} // ForeignToolsSetProperties
873
*-----------------------------------------------------------------------------
875
* ForeignToolsGetToolsState --
883
*-----------------------------------------------------------------------------
887
ForeignToolsGetToolsState(ForeignVMToolsCommand *asyncCommand, // IN
888
VixMsgTrivialRequest *requestMsg) // IN
890
VixError err = VIX_OK;
891
VixPropertyListImpl propList;
892
char *decodedStr = NULL;
893
size_t decodedLength;
895
char *serializedBufferBody = NULL;
896
size_t serializedBufferLength = 0;
897
Bool deleteResultValue = FALSE;
898
char *base64Buffer = NULL;
899
size_t base64BufferLength;
900
char *responseMessage = NULL;
901
size_t responseMessageLength = 0;
903
VixPropertyList_Initialize(&propList);
905
err = VixTools_ProcessVixCommand((VixCommandRequestHeader *) asyncCommand,
906
asyncCommand->asyncOpName,
907
1024 * 1024, // maxResultBufferSize,
918
* If we got a string back from the guest, then decode it and
919
* convert it into a list of properties.
921
if (NULL != base64Buffer) {
922
decodedStr = Util_SafeMalloc(base64BufferLength);
923
success = Base64_Decode(base64Buffer,
928
err = VixPropertyList_Deserialize(&propList, decodedStr, decodedLength);
932
(void) VixPropertyList_SetInteger(&propList,
933
VIX_PROPERTY_VM_TOOLS_STATE,
934
VIX_TOOLSSTATE_RUNNING);
935
} else { // if (NULL == base64Buffer)
936
(void) VixPropertyList_SetInteger(&propList,
937
VIX_PROPERTY_VM_TOOLS_STATE,
938
VIX_TOOLSSTATE_NOT_INSTALLED);
942
* Serialize the property list to buffer
944
err = VixPropertyList_Serialize(&propList,
946
&serializedBufferLength,
947
&serializedBufferBody);
952
responseMessageLength = sizeof(VixMsgGetVMStateResponse)
953
+ serializedBufferLength;
954
responseMessage = Util_SafeMalloc(responseMessageLength);
955
memcpy(responseMessage + sizeof(VixMsgGetVMStateResponse),
956
serializedBufferBody,
957
serializedBufferLength);
958
((VixMsgGetVMStateResponse *) responseMessage)->bufferSize = serializedBufferLength;
960
ForeignToolsSendResponseUsingTotalMessage(asyncCommand->connection,
961
&(asyncCommand->requestHeader),
962
responseMessageLength,
965
0, // additionalError,
967
ForeignToolsDiscardCommand(asyncCommand);
970
* VMAutomation_SendResponseUsingTotalMessage owns responseMessage now,
971
* and it will deallocate it.
973
responseMessage = NULL;
976
VixPropertyList_RemoveAllWithoutHandles(&propList);
978
free(serializedBufferBody);
979
free(responseMessage);
982
} // ForeignToolsGetToolsState
986
*----------------------------------------------------------------------------
988
* ForeignToolsProcessMessage --
990
* Calls the correct handler for a particular message type,
991
* and determines whether to queue more receives.
999
*----------------------------------------------------------------------------
1003
ForeignToolsProcessMessage(ForeignVMToolsConnection *connectionState) //IN
1005
VixError err = VIX_OK;
1006
ForeignVMToolsCommand *commandState = NULL;
1007
uint32 additionalError = 0;
1008
Bool sendResponse = FALSE;
1009
Bool deleteResultValue = FALSE;
1010
char *dummyResponse;
1011
size_t dummyResponseLength;
1013
ASSERT(NULL != connectionState);
1016
* Allocate state for the command.
1018
commandState = Util_SafeCalloc(1, sizeof *commandState);
1019
commandState->connection = connectionState;
1020
commandState->requestHeader = connectionState->requestHeader;
1021
commandState->guestCredentialType = connectionState->requestHeader.userCredentialType;
1022
commandState->guestUserNamePassword = NULL;
1023
commandState->obfuscatedGuestUserNamePassword = NULL;
1024
commandState->obfuscatedCredentialType = 0;
1025
commandState->runProgramOptions = 0;
1026
commandState->responseBody = NULL;
1027
commandState->responseBodyLength = 0;
1029
VIX_ENTER_LOCK(&globalLock);
1030
commandState->next = globalCommandList;
1031
globalCommandList = commandState;
1032
VIX_LEAVE_LOCK(&globalLock);
1034
switch (connectionState->requestHeader.opCode) {
1035
///////////////////////////////////
1036
case VIX_COMMAND_GET_HANDLE_STATE:
1037
err = ForeignToolsGetProperties(commandState,
1038
(VixMsgTrivialRequest *) connectionState->completeRequest);
1041
///////////////////////////////////
1042
case VIX_COMMAND_INSTALL_TOOLS:
1043
case VIX_COMMAND_WAIT_FOR_TOOLS:
1045
sendResponse = TRUE;
1048
///////////////////////////////////
1049
case VIX_COMMAND_GET_DISK_PROPERTIES:
1050
case VIX_COMMAND_CAPTURE_SCREEN:
1051
case VIX_COMMAND_MOUSE_EVENTS:
1052
case VIX_COMMAND_KEYSTROKES:
1053
case VIX_COMMAND_LIST_USB_DEVICES:
1054
err = VIX_E_NOT_SUPPORTED;
1057
///////////////////////////////////
1058
case VIX_CREATE_SESSION_KEY_COMMAND:
1059
err = VIX_E_NOT_SUPPORTED;
1062
///////////////////////////////////
1063
case VIX_COMMAND_SET_HANDLE_STATE:
1064
err = ForeignToolsSetProperties(commandState,
1065
(VixMsgSetVMStateRequest *) (connectionState->completeRequest));
1066
sendResponse = TRUE;
1069
///////////////////////////////////
1070
case VIX_COMMAND_RUN_PROGRAM:
1071
err = ForeignToolsGetUserCredentialForGuest(connectionState, commandState);
1072
if (VIX_OK != err) {
1076
Hostinfo_GetTimeOfDay(&(commandState->programStartTime));
1077
Str_Snprintf(commandState->asyncOpName,
1078
sizeof(commandState->asyncOpName),
1081
commandState->responseBody = NULL;
1083
err = VixTools_ProcessVixCommand((VixCommandRequestHeader *) connectionState->completeRequest,
1084
commandState->asyncOpName,
1085
1024 * 1024, // maxResultBufferSize,
1089
&dummyResponseLength,
1090
&deleteResultValue);
1093
* We don't complete the command until the program exits.
1095
commandState->responseBody = NULL;
1096
commandState->responseBodyLength = 0;
1100
///////////////////////////////////
1103
case VIX_COMMAND_VM_POWEROFF:
1104
case VIX_COMMAND_VM_RESET:
1105
case VIX_COMMAND_RELOAD_VM:
1108
///////////////////////////////////
1110
// These will not be supported.
1111
case VIX_COMMAND_VM_SUSPEND:
1112
case VIX_COMMAND_SET_NIC_BANDWIDTH:
1113
case VIX_COMMAND_UPGRADE_VIRTUAL_HARDWARE:
1114
case VIX_COMMAND_CREATE_RUNNING_VM_SNAPSHOT:
1115
case VIX_COMMAND_CONSOLIDATE_RUNNING_VM_SNAPSHOT:
1119
///////////////////////////////////
1120
case VIX_COMMAND_GET_TOOLS_STATE:
1121
err = ForeignToolsGetToolsState(commandState,
1122
(VixMsgTrivialRequest *) (connectionState->completeRequest));
1125
////////////////////////////////////
1126
case VIX_COMMAND_CHECK_USER_ACCOUNT:
1127
case VIX_COMMAND_LOGOUT_IN_GUEST:
1128
err = ForeignToolsGetUserCredentialForGuest(connectionState, commandState);
1129
if (VIX_OK != err) {
1133
if (VIX_USER_CREDENTIAL_NAME_PASSWORD
1134
== commandState->requestHeader.userCredentialType) {
1135
err = VixTools_ProcessVixCommand((VixCommandRequestHeader *) connectionState->completeRequest,
1136
commandState->asyncOpName,
1137
1024 * 1024, // maxResultBufferSize,
1140
&(commandState->responseBody),
1141
&(commandState->responseBodyLength),
1142
&deleteResultValue);
1144
commandState->responseBody = NULL;
1145
commandState->responseBodyLength = 0;
1148
sendResponse = TRUE;
1152
///////////////////////////////////
1153
// By default, most tools commands do require authentication.
1155
err = ForeignToolsGetUserCredentialForGuest(connectionState, commandState);
1156
if (VIX_OK != err) {
1160
err = VixTools_ProcessVixCommand((VixCommandRequestHeader *) connectionState->completeRequest,
1161
commandState->asyncOpName,
1162
1024 * 1024, // maxResultBufferSize,
1165
&(commandState->responseBody),
1166
&(commandState->responseBodyLength),
1167
&deleteResultValue);
1169
sendResponse = TRUE;
1175
if ((VIX_OK != err) || (sendResponse)) {
1176
if (ForeignToolsIsCommandAlive(commandState)) {
1177
ForeignToolsSendResponse(connectionState,
1178
&(connectionState->requestHeader),
1179
commandState->responseBodyLength,
1180
commandState->responseBody,
1183
0); // responseFlags
1185
if (!deleteResultValue) {
1186
commandState->responseBody = NULL;
1187
commandState->responseBodyLength = 0;
1190
ForeignToolsDiscardCommand(commandState);
1193
} // ForeignToolsProcessMessage