From 62a42ec8ca050326b42722fea9734973ed0ef1aa Mon Sep 17 00:00:00 2001 From: Joshua Duong Date: Thu, 30 Jul 2020 16:34:29 -0700 Subject: [PATCH] [adb] Correctly read host/user name on Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: 162111908 Test: On linux/mac: HOSTNAME="" adb keygen mykey; cat mykey.pub # Also LOGNAME HOSTNAME="测试" adb keygen mykey; cat mykey.pub HOSTNAME="test" adb keygen mykey; cat mykey.pub Test: On Windows: set COMPUTERNAME=&& adb keygen mykey && powershell -command "get-content -encoding utf8 mykey.pub" # Also USERNAME set COMPUTERNAME=测试&& adb keygen mykey && powershell -command "get-content -encoding utf8 mykey.pub" set COMPUTERNAME=test&& adb keygen mykey && powershell -command "get-content -encoding utf8 mykey.pub" Change-Id: I62c952c511a620286aa4e05b1763361406e9f89a --- adb/Android.bp | 42 +++++++++++++ adb/crypto/Android.bp | 2 + adb/crypto/rsa_2048_key.cpp | 28 ++------- adb/crypto/tests/Android.bp | 1 + adb/sysdeps/env.cpp | 122 ++++++++++++++++++++++++++++++++++++ adb/sysdeps/env.h | 35 +++++++++++ adb/sysdeps_win32.cpp | 49 --------------- 7 files changed, 207 insertions(+), 72 deletions(-) create mode 100644 adb/sysdeps/env.cpp create mode 100644 adb/sysdeps/env.h diff --git a/adb/Android.bp b/adb/Android.bp index 87ac54d06..8addf95aa 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -117,6 +117,7 @@ cc_defaults { static_libs: [ "libadb_crypto", "libadb_pairing_connection", + "libadb_sysdeps", "libadb_tls_connection", "libadbd", "libadbd_core", @@ -167,6 +168,7 @@ libadb_srcs = [ "services.cpp", "sockets.cpp", "socket_spec.cpp", + "sysdeps/env.cpp", "sysdeps/errno.cpp", "transport.cpp", "transport_fd.cpp", @@ -261,6 +263,43 @@ cc_library_host_static { ], } +cc_library { + name: "libadb_sysdeps", + defaults: ["adb_defaults"], + recovery_available: true, + host_supported: true, + compile_multilib: "both", + min_sdk_version: "apex_inherit", + + srcs: [ + "sysdeps/env.cpp", + ], + + shared_libs: [ + "libbase", + "liblog", + ], + + target: { + windows: { + enabled: true, + ldflags: ["-municode"], + }, + }, + + export_include_dirs: ["."], + + visibility: [ + "//system/core/adb:__subpackages__", + "//bootable/recovery/minadbd:__subpackages__", + ], + + apex_available: [ + "com.android.adbd", + "test_com.android.adbd", + ], +} + cc_test_host { name: "adb_test", defaults: ["adb_defaults"], @@ -274,6 +313,7 @@ cc_test_host { "libadb_pairing_auth_static", "libadb_pairing_connection_static", "libadb_protos_static", + "libadb_sysdeps", "libadb_tls_connection_static", "libbase", "libcutils", @@ -330,6 +370,7 @@ cc_binary_host { "libadb_pairing_auth", "libadb_pairing_connection", "libadb_protos", + "libadb_sysdeps", "libadb_tls_connection", "libandroidfw", "libapp_processes_protos_full", @@ -831,6 +872,7 @@ cc_test_host { "libadb_pairing_auth_static", "libadb_pairing_connection_static", "libadb_protos_static", + "libadb_sysdeps", "libadb_tls_connection_static", "libandroidfw", "libbase", diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp index 9d14b030a..e2c27f1f3 100644 --- a/adb/crypto/Android.bp +++ b/adb/crypto/Android.bp @@ -48,6 +48,7 @@ cc_defaults { shared_libs: [ "libadb_protos", + "libadb_sysdeps", "libbase", "liblog", "libcrypto", @@ -76,5 +77,6 @@ cc_library_static { static_libs: [ "libadb_protos_static", + "libadb_sysdeps", ], } diff --git a/adb/crypto/rsa_2048_key.cpp b/adb/crypto/rsa_2048_key.cpp index 7911af95f..6d9ee3054 100644 --- a/adb/crypto/rsa_2048_key.cpp +++ b/adb/crypto/rsa_2048_key.cpp @@ -20,32 +20,11 @@ #include #include #include +#include namespace adb { namespace crypto { -namespace { -std::string get_user_info() { - std::string hostname; - if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME"); -#if !defined(_WIN32) - char buf[64]; - if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf; -#endif - if (hostname.empty()) hostname = "unknown"; - - std::string username; - if (getenv("LOGNAME")) username = getenv("LOGNAME"); -#if !defined(_WIN32) - if (username.empty() && getlogin()) username = getlogin(); -#endif - if (username.empty()) hostname = "unknown"; - - return " " + username + "@" + hostname; -} - -} // namespace - bool CalculatePublicKey(std::string* out, RSA* private_key) { uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE]; if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) { @@ -63,7 +42,10 @@ bool CalculatePublicKey(std::string* out, RSA* private_key) { size_t actual_length = EVP_EncodeBlock(reinterpret_cast(out->data()), binary_key_data, sizeof(binary_key_data)); out->resize(actual_length); - out->append(get_user_info()); + out->append(" "); + out->append(sysdeps::GetLoginNameUTF8()); + out->append("@"); + out->append(sysdeps::GetHostNameUTF8()); return true; } diff --git a/adb/crypto/tests/Android.bp b/adb/crypto/tests/Android.bp index b32dcf731..b04105545 100644 --- a/adb/crypto/tests/Android.bp +++ b/adb/crypto/tests/Android.bp @@ -35,6 +35,7 @@ cc_test { static_libs: [ "libadb_crypto_static", "libadb_protos_static", + "libadb_sysdeps", ], test_suites: ["device-tests"], diff --git a/adb/sysdeps/env.cpp b/adb/sysdeps/env.cpp new file mode 100644 index 000000000..40587280c --- /dev/null +++ b/adb/sysdeps/env.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed 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 "sysdeps/env.h" + +#ifdef _WIN32 +#include +#include +#endif // _WIN32 + +#include + +namespace adb { +namespace sysdeps { + +std::optional GetEnvironmentVariable(std::string_view var) { + if (var.empty()) { + return std::nullopt; + } + +#ifdef _WIN32 + constexpr size_t kMaxEnvVarSize = 32767; + wchar_t wbuf[kMaxEnvVarSize]; + std::wstring wvar; + if (!android::base::UTF8ToWide(var.data(), &wvar)) { + return std::nullopt; + } + + auto sz = ::GetEnvironmentVariableW(wvar.data(), wbuf, sizeof(wbuf)); + if (sz == 0) { + return std::nullopt; + } + + std::string val; + if (!android::base::WideToUTF8(wbuf, &val)) { + return std::nullopt; + } + + return std::make_optional(val); +#else // !_WIN32 + const char* val = getenv(var.data()); + if (val == nullptr) { + return std::nullopt; + } + + return std::make_optional(std::string(val)); +#endif +} + +#ifdef _WIN32 +constexpr char kHostNameEnvVar[] = "COMPUTERNAME"; +constexpr char kUserNameEnvVar[] = "USERNAME"; +#else +constexpr char kHostNameEnvVar[] = "HOSTNAME"; +constexpr char kUserNameEnvVar[] = "LOGNAME"; +#endif + +std::string GetHostNameUTF8() { + const auto hostName = GetEnvironmentVariable(kHostNameEnvVar); + if (hostName && !hostName->empty()) { + return *hostName; + } + +#ifdef _WIN32 + wchar_t wbuf[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD size = sizeof(wbuf); + if (!GetComputerNameW(wbuf, &size) || size == 0) { + return ""; + } + + std::string name; + if (!android::base::WideToUTF8(wbuf, &name)) { + return ""; + } + + return name; +#else // !_WIN32 + char buf[256]; + return (gethostname(buf, sizeof(buf)) == -1) ? "" : buf; +#endif // _WIN32 +} + +std::string GetLoginNameUTF8() { + const auto userName = GetEnvironmentVariable(kUserNameEnvVar); + if (userName && !userName->empty()) { + return *userName; + } + +#ifdef _WIN32 + wchar_t wbuf[UNLEN + 1]; + DWORD size = sizeof(wbuf); + if (!GetUserNameW(wbuf, &size) || size == 0) { + return ""; + } + + std::string login; + if (!android::base::WideToUTF8(wbuf, &login)) { + return ""; + } + + return login; +#else // !_WIN32 + const char* login = getlogin(); + return login ? login : ""; +#endif // _WIN32 +} + +} // namespace sysdeps +} // namespace adb diff --git a/adb/sysdeps/env.h b/adb/sysdeps/env.h new file mode 100644 index 000000000..b39b675cb --- /dev/null +++ b/adb/sysdeps/env.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed 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. + */ + +#pragma once + +#include +#include + +namespace adb { +namespace sysdeps { + +// Attempts to retrieve the environment variable value for |var|. Returns std::nullopt +// if unset. +std::optional GetEnvironmentVariableUTF8(std::string_view var); + +// Gets the host name of the system. Returns empty string on failure. +std::string GetHostNameUTF8(); +// Gets the current login user. Returns empty string on failure. +std::string GetLoginNameUTF8(); + +} // namespace sysdeps +} // namespace adb diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp index be82bc0d1..217a6b7f8 100644 --- a/adb/sysdeps_win32.cpp +++ b/adb/sysdeps_win32.cpp @@ -1010,55 +1010,6 @@ int adb_register_socket(SOCKET s) { return _fh_to_int(f); } -static bool isBlankStr(const char* str) { - for (; *str != '\0'; ++str) { - if (!isblank(*str)) { - return false; - } - } - return true; -} - -int adb_gethostname(char* name, size_t len) { - const char* computerName = adb_getenv("COMPUTERNAME"); - if (computerName && !isBlankStr(computerName)) { - strncpy(name, computerName, len); - name[len - 1] = '\0'; - return 0; - } - - wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD size = sizeof(buffer); - if (!GetComputerNameW(buffer, &size)) { - return -1; - } - std::string name_utf8; - if (!android::base::WideToUTF8(buffer, &name_utf8)) { - return -1; - } - - strncpy(name, name_utf8.c_str(), len); - name[len - 1] = '\0'; - return 0; -} - -int adb_getlogin_r(char* buf, size_t bufsize) { - wchar_t buffer[UNLEN + 1]; - DWORD len = sizeof(buffer); - if (!GetUserNameW(buffer, &len)) { - return -1; - } - - std::string login; - if (!android::base::WideToUTF8(buffer, &login)) { - return -1; - } - - strncpy(buf, login.c_str(), bufsize); - buf[bufsize - 1] = '\0'; - return 0; -} - #undef accept int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, socklen_t* addrlen) { FH serverfh = _fh_from_int(serverfd, __func__);