blob: e3a2c37240de960e019d6d1aa90379b8e404a220 [file] [log] [blame]
/**
* 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 <Winsvc.h>
#include <errno.h>
#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;
}