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 namespace grpc_core {
35 namespace internal {
36 
check_bios_data(const char *)37 bool check_bios_data(const char*) { return false; }
38 
check_windows_registry_product_name(HKEY root_key,const char * reg_key_path,const char * reg_key_name)39 bool check_windows_registry_product_name(HKEY root_key,
40                                          const char* reg_key_path,
41                                          const char* reg_key_name) {
42   const size_t kProductNameBufferSize = 256;
43   char const expected_substr[] = "Google";
44 
45   // Get the size of the string first to allocate our buffer. This includes
46   // enough space for the trailing NUL character that will be included.
47   DWORD buffer_size{};
48   auto rc = ::RegGetValueA(
49       root_key, reg_key_path, reg_key_name, RRF_RT_REG_SZ,
50       nullptr,        // We know the type will be REG_SZ.
51       nullptr,        // We're only fetching the size; no buffer given yet.
52       &buffer_size);  // Fetch the size in bytes of the value, if it exists.
53   if (rc != 0) {
54     return false;
55   }
56 
57   if (buffer_size > kProductNameBufferSize) {
58     return false;
59   }
60 
61   // Retrieve the product name string.
62   char buffer[kProductNameBufferSize];
63   buffer_size = kProductNameBufferSize;
64   rc = ::RegGetValueA(
65       root_key, reg_key_path, reg_key_name, RRF_RT_REG_SZ,
66       nullptr,                     // We know the type will be REG_SZ.
67       static_cast<void*>(buffer),  // Fetch the string value this time.
68       &buffer_size);  // The string size in bytes, not including trailing NUL.
69   if (rc != 0) {
70     return false;
71   }
72 
73   return strstr(buffer, expected_substr) != nullptr;
74 }
75 
76 }  // namespace internal
77 }  // namespace grpc_core
78 
79 static bool g_compute_engine_detection_done = false;
80 static bool g_is_on_compute_engine = false;
81 static gpr_mu g_mu;
82 static gpr_once g_once = GPR_ONCE_INIT;
83 
init_mu(void)84 static void init_mu(void) { gpr_mu_init(&g_mu); }
85 
grpc_alts_is_running_on_gcp()86 bool grpc_alts_is_running_on_gcp() {
87   char const reg_key_path[] = "SYSTEM\\HardwareConfig\\Current\\";
88   char const reg_key_name[] = "SystemProductName";
89 
90   gpr_once_init(&g_once, init_mu);
91   gpr_mu_lock(&g_mu);
92   if (!g_compute_engine_detection_done) {
93     g_is_on_compute_engine =
94         grpc_core::internal::check_windows_registry_product_name(
95             HKEY_LOCAL_MACHINE, reg_key_path, reg_key_name);
96     g_compute_engine_detection_done = true;
97   }
98   gpr_mu_unlock(&g_mu);
99   return g_is_on_compute_engine;
100 }
101 
102 #endif  // GPR_WINDOWS
103