[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
This commit is contained in:
Joshua Duong 2020-07-30 16:34:29 -07:00
parent 3b8b444fce
commit 62a42ec8ca
7 changed files with 207 additions and 72 deletions

View file

@ -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",

View file

@ -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",
],
}

View file

@ -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 @@ bool CalculatePublicKey(std::string* out, RSA* private_key) {
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;
}

View file

@ -35,6 +35,7 @@ cc_test {
static_libs: [
"libadb_crypto_static",
"libadb_protos_static",
"libadb_sysdeps",
],
test_suites: ["device-tests"],

122
adb/sysdeps/env.cpp Normal file
View file

@ -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

35
adb/sysdeps/env.h Normal file
View file

@ -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

View file

@ -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__);