/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ #include "winutils.h" #include #include #include "hadoopwinutilsvc_h.h" #pragma comment(lib, "Rpcrt4.lib") #pragma comment(lib, "advapi32.lib") static ACCESS_MASK CLIENT_MASK = 1; VOID ReportClientError(LPWSTR lpszLocation, DWORD dwError) { LPWSTR debugMsg = NULL; int len; if (IsDebuggerPresent()) { len = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&debugMsg, 0, NULL); LogDebugMessage(L"%s: %s: %x: %.*s\n", GetSystemTimeString(), lpszLocation, dwError, len, debugMsg); } if (NULL != debugMsg) LocalFree(debugMsg); } DWORD PrepareRpcBindingHandle( __out RPC_BINDING_HANDLE* pHadoopWinutilsSvcBinding) { DWORD dwError = EXIT_FAILURE; RPC_STATUS status; LPWSTR lpszStringBinding = NULL; RPC_SECURITY_QOS_V3 qos; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; BOOL rpcBindingInit = FALSE; PSID pLocalSystemSid = NULL; DWORD cbSystemSidSize = SECURITY_MAX_SID_SIZE; pLocalSystemSid = (PSID) LocalAlloc(LPTR, cbSystemSidSize); if (!pLocalSystemSid) { dwError = GetLastError(); ReportClientError(L"LocalAlloc", dwError); goto done; } if (!CreateWellKnownSid(WinLocalSystemSid, NULL, pLocalSystemSid, &cbSystemSidSize)) { dwError = GetLastError(); ReportClientError(L"CreateWellKnownSid", dwError); goto done; } ZeroMemory(&qos, sizeof(qos)); qos.Version = RPC_C_SECURITY_QOS_VERSION_3; qos.Capabilities = RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT | RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC; qos.ImpersonationType = RPC_C_IMP_LEVEL_DEFAULT; qos.Sid = pLocalSystemSid; status = RpcStringBindingCompose(NULL, SVCBINDING, NULL, SVCNAME, NULL, &lpszStringBinding); if (RPC_S_OK != status) { ReportClientError(L"RpcStringBindingCompose", status); dwError = status; goto done; } status = RpcBindingFromStringBinding(lpszStringBinding, pHadoopWinutilsSvcBinding); if (RPC_S_OK != status) { ReportClientError(L"RpcBindingFromStringBinding", status); dwError = status; goto done; } rpcBindingInit = TRUE; status = RpcBindingSetAuthInfoEx( *pHadoopWinutilsSvcBinding, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // AuthnLevel RPC_C_AUTHN_WINNT, // AuthnSvc NULL, // AuthnIdentity (self) RPC_C_AUTHZ_NONE, // AuthzSvc (RPC_SECURITY_QOS*) &qos); if (RPC_S_OK != status) { ReportClientError(L"RpcBindingSetAuthInfoEx", status); dwError = status; goto done; } dwError = ERROR_SUCCESS; done: if (dwError && rpcBindingInit) RpcBindingFree(pHadoopWinutilsSvcBinding); if (pLocalSystemSid) LocalFree(pLocalSystemSid); if (NULL != lpszStringBinding) { status = RpcStringFree(&lpszStringBinding); if (RPC_S_OK != status) { ReportClientError(L"RpcStringFree", status); } } return dwError; } DWORD RpcCall_WinutilsKillTask( __in LPCWSTR taskName) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; KILLTASK_REQUEST request; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.taskName = taskName; RpcTryExcept { dwError = WinutilsKillTask(hHadoopWinutilsSvcBinding, &request); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); LogDebugMessage(L"RpcCall_WinutilsKillTask: %s :%d\n", taskName, dwError); return dwError; } DWORD RpcCall_WinutilsMkDir( __in LPCWSTR filePath) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; MKDIR_REQUEST request; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.filePath = filePath; RpcTryExcept { dwError = WinutilsMkDir(hHadoopWinutilsSvcBinding, &request); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); LogDebugMessage(L"RpcCall_WinutilsMkDir: %s :%d\n", filePath, dwError); return dwError; } DWORD RpcCall_WinutilsChown( __in LPCWSTR filePath, __in_opt LPCWSTR ownerName, __in_opt LPCWSTR groupName) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; CHOWN_REQUEST request; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.filePath = filePath; request.ownerName = ownerName; request.groupName = groupName; RpcTryExcept { dwError = WinutilsChown(hHadoopWinutilsSvcBinding, &request); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); LogDebugMessage(L"RpcCall_WinutilsChown: %s %s %s :%d\n", ownerName, groupName, filePath, dwError); return dwError; } DWORD RpcCall_WinutilsChmod( __in LPCWSTR filePath, __in int mode) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; CHMOD_REQUEST request; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.filePath = filePath; request.mode = mode; RpcTryExcept { dwError = WinutilsChmod(hHadoopWinutilsSvcBinding, &request); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); LogDebugMessage(L"RpcCall_WinutilsChmod: %s %o :%d\n", filePath, mode, dwError); return dwError; } DWORD RpcCall_WinutilsMoveFile( __in int operation, __in LPCWSTR sourcePath, __in LPCWSTR destinationPath, __in BOOL replaceExisting) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; MOVEFILE_REQUEST request; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.operation = operation; request.sourcePath = sourcePath; request.destinationPath = destinationPath; request.replaceExisting = replaceExisting; RpcTryExcept { dwError = WinutilsMoveFile(hHadoopWinutilsSvcBinding, &request); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); LogDebugMessage(L"RpcCall_WinutilsMoveFile: %s %s %d :%d\n", sourcePath, destinationPath, replaceExisting, dwError); return dwError; } DWORD RpcCall_WinutilsCreateFile( __in LPCWSTR path, __in DWORD desiredAccess, __in DWORD shareMode, __in DWORD creationDisposition, __in DWORD flags, __out HANDLE* hFile) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; DWORD dwSelfPid = GetCurrentProcessId(); CREATEFILE_REQUEST request; CREATEFILE_RESPONSE *response = NULL; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.path = path; request.desiredAccess = desiredAccess; request.shareMode = shareMode; request.creationDisposition = creationDisposition; request.flags = flags; RpcTryExcept { dwError = WinutilsCreateFile(hHadoopWinutilsSvcBinding, dwSelfPid, &request, &response); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; if (ERROR_SUCCESS == dwError) { *hFile = (HANDLE) response->hFile; } done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); if(NULL != response) MIDL_user_free(response); LogDebugMessage(L"RpcCall_WinutilsCreateFile: %s %d, %d, %d, %d :%d\n", path, desiredAccess, shareMode, creationDisposition, flags, dwError); return dwError; } DWORD RpcCall_WinutilsDeletePath( __in LPCWSTR path, __in BOOL isDir, __out BOOL* pDeleted) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; DELETEPATH_REQUEST request; DELETEPATH_RESPONSE *response = NULL; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; pDeleted = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.path = path; request.type = isDir ? PATH_IS_DIR : PATH_IS_FILE; RpcTryExcept { dwError = WinutilsDeletePath(hHadoopWinutilsSvcBinding, &request, &response); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; if (ERROR_SUCCESS == dwError) { *pDeleted = response->deleted; } done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); if(NULL != response) MIDL_user_free(response); LogDebugMessage(L"RpcCall_WinutilsDeletePath: %s %d: %d %d\n", path, isDir, *pDeleted, dwError); return dwError; } DWORD RpcCall_TaskCreateAsUser( LPCWSTR cwd, LPCWSTR jobName, LPCWSTR user, LPCWSTR pidFile, LPCWSTR cmdLine, HANDLE* phProcess, HANDLE* phThread, HANDLE* phStdIn, HANDLE* phStdOut, HANDLE* phStdErr) { DWORD dwError = EXIT_FAILURE; ULONG ulCode; DWORD dwSelfPid = GetCurrentProcessId(); CREATE_PROCESS_REQUEST request; CREATE_PROCESS_RESPONSE *response = NULL; RPC_BINDING_HANDLE hHadoopWinutilsSvcBinding; BOOL rpcBindingInit = FALSE; dwError = PrepareRpcBindingHandle(&hHadoopWinutilsSvcBinding); if (dwError) { ReportClientError(L"PrepareRpcBindingHandle", dwError); goto done; } rpcBindingInit = TRUE; ZeroMemory(&request, sizeof(request)); request.cwd = cwd; request.jobName = jobName; request.user = user; request.pidFile = pidFile; request.cmdLine = cmdLine; RpcTryExcept { dwError = WinutilsCreateProcessAsUser(hHadoopWinutilsSvcBinding, dwSelfPid, &request, &response); } RpcExcept(1) { ulCode = RpcExceptionCode(); ReportClientError(L"RpcExcept", ulCode); dwError = (DWORD) ulCode; } RpcEndExcept; if (ERROR_SUCCESS == dwError) { *phProcess = (HANDLE) response->hProcess; *phThread = (HANDLE) response->hThread; *phStdIn = (HANDLE) response->hStdIn; *phStdOut = (HANDLE) response->hStdOut; *phStdErr = (HANDLE) response->hStdErr; } done: if (rpcBindingInit) RpcBindingFree(&hHadoopWinutilsSvcBinding); if (NULL != response) { MIDL_user_free(response); } return dwError; }