• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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