[adb] Correctly read host/user name on Windows.
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
diff --git a/adb/Android.bp b/adb/Android.bp
index 87ac54d..8addf95 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -117,6 +117,7 @@
static_libs: [
"libadb_crypto",
"libadb_pairing_connection",
+ "libadb_sysdeps",
"libadb_tls_connection",
"libadbd",
"libadbd_core",
@@ -167,6 +168,7 @@
"services.cpp",
"sockets.cpp",
"socket_spec.cpp",
+ "sysdeps/env.cpp",
"sysdeps/errno.cpp",
"transport.cpp",
"transport_fd.cpp",
@@ -261,6 +263,43 @@
],
}
+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 @@
"libadb_pairing_auth_static",
"libadb_pairing_connection_static",
"libadb_protos_static",
+ "libadb_sysdeps",
"libadb_tls_connection_static",
"libbase",
"libcutils",
@@ -330,6 +370,7 @@
"libadb_pairing_auth",
"libadb_pairing_connection",
"libadb_protos",
+ "libadb_sysdeps",
"libadb_tls_connection",
"libandroidfw",
"libapp_processes_protos_full",
@@ -831,6 +872,7 @@
"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 9d14b03..e2c27f1 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -48,6 +48,7 @@
shared_libs: [
"libadb_protos",
+ "libadb_sysdeps",
"libbase",
"liblog",
"libcrypto",
@@ -76,5 +77,6 @@
static_libs: [
"libadb_protos_static",
+ "libadb_sysdeps",
],
}
diff --git a/adb/crypto/rsa_2048_key.cpp b/adb/crypto/rsa_2048_key.cpp
index 7911af9..6d9ee30 100644
--- a/adb/crypto/rsa_2048_key.cpp
+++ b/adb/crypto/rsa_2048_key.cpp
@@ -20,32 +20,11 @@
#include <crypto_utils/android_pubkey.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
+#include <sysdeps/env.h>
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 @@
size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(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 b32dcf7..b041055 100644
--- a/adb/crypto/tests/Android.bp
+++ b/adb/crypto/tests/Android.bp
@@ -35,6 +35,7 @@
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 0000000..4058728
--- /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 <lmcons.h>
+#include <windows.h>
+#endif // _WIN32
+
+#include <android-base/utf8.h>
+
+namespace adb {
+namespace sysdeps {
+
+std::optional<std::string> 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 0000000..b39b675
--- /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 <optional>
+#include <string>
+
+namespace adb {
+namespace sysdeps {
+
+// Attempts to retrieve the environment variable value for |var|. Returns std::nullopt
+// if unset.
+std::optional<std::string> 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 be82bc0..217a6b7 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -1010,55 +1010,6 @@
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__);