1 /*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #ifdef GPR_WINDOWS
22
23 #include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
24
25 #include <shellapi.h>
26 #include <stdio.h>
27 #include <tchar.h>
28 #include <windows.h>
29
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/sync.h>
33
34 #define GRPC_ALTS_EXPECT_NAME_GOOGLE "Google"
35 #define GRPC_ALTS_WINDOWS_CHECK_COMMAND "powershell.exe"
36 #define GRPC_ALTS_WINDOWS_CHECK_COMMAND_ARGS \
37 "(Get-WmiObject -Class Win32_BIOS).Manufacturer"
38 #define GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE "windows_bios.data"
39
40 const size_t kBiosDataBufferSize = 256;
41
42 static bool g_compute_engine_detection_done = false;
43 static bool g_is_on_compute_engine = false;
44 static gpr_mu g_mu;
45 static gpr_once g_once = GPR_ONCE_INIT;
46
47 namespace grpc_core {
48 namespace internal {
49
check_bios_data(const char * bios_data_file)50 bool check_bios_data(const char* bios_data_file) {
51 char* bios_data = read_bios_file(bios_data_file);
52 bool result = !strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE);
53 remove(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE);
54 gpr_free(bios_data);
55 return result;
56 }
57
58 } // namespace internal
59 } // namespace grpc_core
60
init_mu(void)61 static void init_mu(void) { gpr_mu_init(&g_mu); }
62
run_powershell()63 static bool run_powershell() {
64 SECURITY_ATTRIBUTES sa;
65 sa.nLength = sizeof(sa);
66 sa.lpSecurityDescriptor = NULL;
67 sa.bInheritHandle = TRUE;
68 HANDLE h = CreateFile(_T(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE), GENERIC_WRITE,
69 FILE_SHARE_WRITE | FILE_SHARE_READ, &sa, OPEN_ALWAYS,
70 FILE_ATTRIBUTE_NORMAL, NULL);
71 if (h == INVALID_HANDLE_VALUE) {
72 gpr_log(GPR_ERROR, "CreateFile failed (%d).", GetLastError());
73 return false;
74 }
75 PROCESS_INFORMATION pi;
76 STARTUPINFO si;
77 DWORD flags = CREATE_NO_WINDOW;
78 ZeroMemory(&pi, sizeof(pi));
79 ZeroMemory(&si, sizeof(si));
80 si.cb = sizeof(si);
81 si.dwFlags |= STARTF_USESTDHANDLES;
82 si.hStdInput = NULL;
83 si.hStdError = h;
84 si.hStdOutput = h;
85 TCHAR cmd[kBiosDataBufferSize];
86 _sntprintf(cmd, kBiosDataBufferSize, _T("%s %s"),
87 _T(GRPC_ALTS_WINDOWS_CHECK_COMMAND),
88 _T(GRPC_ALTS_WINDOWS_CHECK_COMMAND_ARGS));
89 if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si,
90 &pi)) {
91 gpr_log(GPR_ERROR, "CreateProcess failed (%d).\n", GetLastError());
92 return false;
93 }
94 WaitForSingleObject(pi.hProcess, INFINITE);
95 CloseHandle(pi.hProcess);
96 CloseHandle(pi.hThread);
97 CloseHandle(h);
98 return true;
99 }
100
grpc_alts_is_running_on_gcp()101 bool grpc_alts_is_running_on_gcp() {
102 gpr_once_init(&g_once, init_mu);
103 gpr_mu_lock(&g_mu);
104 if (!g_compute_engine_detection_done) {
105 g_is_on_compute_engine =
106 run_powershell() &&
107 grpc_core::internal::check_bios_data(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE);
108 g_compute_engine_detection_done = true;
109 }
110 gpr_mu_unlock(&g_mu);
111 return g_is_on_compute_engine;
112 }
113
114 #endif // GPR_WINDOWS
115