Loading adb/Android.mk +16 −6 Original line number Diff line number Diff line Loading @@ -17,32 +17,34 @@ ifeq ($(HOST_OS),linux) USB_SRCS := usb_linux.c EXTRA_SRCS := get_my_path_linux.c LOCAL_LDLIBS += -lrt -lncurses -lpthread LOCAL_SHARED_LIBRARIES := libcrypto endif ifeq ($(HOST_OS),darwin) USB_SRCS := usb_osx.c EXTRA_SRCS := get_my_path_darwin.c LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon LOCAL_LDLIBS += -lpthread -lcrypto -framework CoreFoundation -framework IOKit -framework Carbon endif ifeq ($(HOST_OS),freebsd) USB_SRCS := usb_libusb.c EXTRA_SRCS := get_my_path_freebsd.c LOCAL_LDLIBS += -lpthread -lusb LOCAL_SHARED_LIBRARIES := libcrypto endif ifeq ($(HOST_OS),windows) USB_SRCS := usb_windows.c EXTRA_SRCS := get_my_path_windows.c EXTRA_STATIC_LIBS := AdbWinApi EXTRA_SRCS := get_my_path_windows.c ../libcutils/list.c EXTRA_STATIC_LIBS := AdbWinApi libcrypto_static ifneq ($(strip $(USE_CYGWIN)),) # Pure cygwin case LOCAL_LDLIBS += -lpthread LOCAL_LDLIBS += -lpthread -lgdi32 LOCAL_C_INCLUDES += /usr/include/w32api/ddk endif ifneq ($(strip $(USE_MINGW)),) # MinGW under Linux case LOCAL_LDLIBS += -lws2_32 LOCAL_LDLIBS += -lws2_32 -lgdi32 USE_SYSDEPS_WIN32 := 1 LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk endif Loading @@ -57,6 +59,7 @@ LOCAL_SRC_FILES := \ transport_usb.c \ commandline.c \ adb_client.c \ adb_auth_host.c \ sockets.c \ services.c \ file_sync_client.c \ Loading @@ -65,6 +68,7 @@ LOCAL_SRC_FILES := \ utils.c \ usb_vendors.c LOCAL_C_INCLUDES += external/openssl/include ifneq ($(USE_SYSDEPS_WIN32),) LOCAL_SRC_FILES += sysdeps_win32.c Loading Loading @@ -104,6 +108,7 @@ LOCAL_SRC_FILES := \ transport.c \ transport_local.c \ transport_usb.c \ adb_auth_client.c \ sockets.c \ services.c \ file_sync_service.c \ Loading @@ -127,7 +132,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) LOCAL_STATIC_LIBRARIES := libcutils libc LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt include $(BUILD_EXECUTABLE) Loading @@ -146,6 +151,7 @@ LOCAL_SRC_FILES := \ transport_usb.c \ commandline.c \ adb_client.c \ adb_auth_host.c \ sockets.c \ services.c \ file_sync_client.c \ Loading @@ -165,9 +171,13 @@ LOCAL_CFLAGS := \ -D_XOPEN_SOURCE \ -D_GNU_SOURCE LOCAL_C_INCLUDES += external/openssl/include LOCAL_MODULE := adb LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils LOCAL_SHARED_LIBRARIES := libcrypto include $(BUILD_EXECUTABLE) endif adb/adb.c +114 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) Loading @@ -46,6 +47,8 @@ ADB_MUTEX_DEFINE( D_lock ); int HOST = 0; static int auth_enabled = 0; #if !ADB_HOST static const char *adb_device_banner = "device"; #endif Loading Loading @@ -100,6 +103,7 @@ void adb_trace_init(void) { "transport", TRACE_TRANSPORT }, { "jdwp", TRACE_JDWP }, { "services", TRACE_SERVICES }, { "auth", TRACE_AUTH }, { NULL, 0 } }; Loading Loading @@ -203,19 +207,21 @@ void put_apacket(apacket *p) free(p); } void handle_online(void) void handle_online(atransport *t) { D("adb: online\n"); t->online = 1; } void handle_offline(atransport *t) { D("adb: offline\n"); //Close the associated usb t->online = 0; run_transport_disconnects(t); } #if TRACE_PACKETS #if DEBUG_PACKETS #define DUMPMAX 32 void print_packet(const char *label, apacket *p) { Loading @@ -230,6 +236,7 @@ void print_packet(const char *label, apacket *p) case A_OKAY: tag = "OKAY"; break; case A_CLSE: tag = "CLSE"; break; case A_WRTE: tag = "WRTE"; break; case A_AUTH: tag = "AUTH"; break; default: tag = "????"; break; } Loading @@ -251,7 +258,7 @@ void print_packet(const char *label, apacket *p) } x++; } fprintf(stderr, tag); fputs(tag, stderr); } #endif Loading Loading @@ -315,11 +322,70 @@ static void send_connect(atransport *t) cp->msg.data_length = fill_connect_data((char *)cp->data, sizeof(cp->data)); send_packet(cp, t); #if ADB_HOST /* XXX why sleep here? */ // allow the device some time to respond to the connect message adb_sleep_ms(1000); #endif } static void send_auth_request(atransport *t) { D("Calling send_auth_request\n"); apacket *p; int ret; ret = adb_auth_generate_token(t->token, sizeof(t->token)); if (ret != sizeof(t->token)) { D("Error generating token ret=%d\n", ret); return; } p = get_apacket(); memcpy(p->data, t->token, ret); p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_TOKEN; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_response(uint8_t *token, size_t token_size, atransport *t) { D("Calling send_auth_response\n"); apacket *p = get_apacket(); int ret; ret = adb_auth_sign(t->key, token, token_size, p->data); if (!ret) { D("Error signing the token\n"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_publickey(atransport *t) { D("Calling send_auth_publickey\n"); apacket *p = get_apacket(); int ret; ret = adb_auth_get_userkey(p->data, sizeof(p->data)); if (!ret) { D("Failed to get user public key\n"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY; p->msg.data_length = ret; send_packet(p, t); } void adb_auth_verified(atransport *t) { handle_online(t); send_connect(t); } static char *connection_state_name(atransport *t) Loading Loading @@ -451,13 +517,42 @@ void handle_packet(apacket *p, atransport *t) t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner((char*) p->data, t); handle_online(); if (HOST || !auth_enabled) { handle_online(t); if(!HOST) send_connect(t); } else { send_auth_request(t); } break; case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { adb_auth_confirm_key(p->data, p->msg.data_length, t); } break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); Loading @@ -473,7 +568,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_OKAY: /* READY(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { if(s->peer == 0) { s->peer = create_remote_socket(p->msg.arg0, t); Loading @@ -485,7 +580,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_CLSE: /* CLOSE(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { s->close(s); } Loading @@ -493,7 +588,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_WRTE: if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; Loading Loading @@ -1014,6 +1109,7 @@ int adb_main(int is_daemon, int server_port) usb_vendors_init(); usb_init(); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); adb_auth_init(); char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); Loading @@ -1021,6 +1117,10 @@ int adb_main(int is_daemon, int server_port) exit(1); } #else property_get("ro.adb.secure", value, "0"); auth_enabled = !strcmp(value, "1"); if (auth_enabled) adb_auth_init(); /* don't listen on a port (default 5037) if running in secure mode */ /* don't run as root if we are running in secure mode */ Loading adb/adb.h +12 −2 Original line number Diff line number Diff line Loading @@ -29,13 +29,14 @@ #define A_OKAY 0x59414b4f #define A_CLSE 0x45534c43 #define A_WRTE 0x45545257 #define A_AUTH 0x48545541 #define A_VERSION 0x01000000 // ADB protocol version #define ADB_VERSION_MAJOR 1 // Used for help/version information #define ADB_VERSION_MINOR 0 // Used for help/version information #define ADB_SERVER_VERSION 29 // Increment this when we want to force users to start a new adb server #define ADB_SERVER_VERSION 30 // Increment this when we want to force users to start a new adb server typedef struct amessage amessage; typedef struct apacket apacket; Loading Loading @@ -165,6 +166,8 @@ typedef enum transport_type { kTransportHost, } transport_type; #define TOKEN_SIZE 20 struct atransport { atransport *next; Loading @@ -181,6 +184,7 @@ struct atransport int ref_count; unsigned sync_token; int connection_state; int online; transport_type type; /* usb handle or socket fd as needed */ Loading @@ -198,6 +202,11 @@ struct atransport /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; adisconnect disconnects; void *key; unsigned char token[TOKEN_SIZE]; fdevent auth_fde; unsigned failed_auth_attempts; }; Loading Loading @@ -349,6 +358,7 @@ typedef enum { TRACE_SYSDEPS, TRACE_JDWP, /* 0x100 */ TRACE_SERVICES, TRACE_AUTH, } AdbTrace; #if ADB_TRACE Loading Loading @@ -408,7 +418,7 @@ void adb_qemu_trace(const char* fmt, ...); #endif #if !TRACE_PACKETS #if !DEBUG_PACKETS #define print_packet(tag,p) do {} while (0) #endif Loading adb/adb_auth.h 0 → 100644 +54 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 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. */ #ifndef __ADB_AUTH_H #define __ADB_AUTH_H void adb_auth_init(void); void adb_auth_verified(atransport *t); /* AUTH packets first argument */ /* Request */ #define ADB_AUTH_TOKEN 1 /* Response */ #define ADB_AUTH_SIGNATURE 2 #define ADB_AUTH_RSAPUBLICKEY 3 #if ADB_HOST int adb_auth_sign(void *key, void *token, size_t token_size, void *sig); void *adb_auth_nextkey(void *current); int adb_auth_get_userkey(unsigned char *data, size_t len); static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; } static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { } static inline void adb_auth_reload_keys(void) { } #else // !ADB_HOST static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; } static inline void *adb_auth_nextkey(void *current) { return NULL; } static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; } int adb_auth_generate_token(void *token, size_t token_size); int adb_auth_verify(void *token, void *sig, int siglen); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); void adb_auth_reload_keys(void); #endif // ADB_HOST #endif // __ADB_AUTH_H adb/adb_auth_client.c 0 → 100644 +245 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 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 <stdio.h> #include <string.h> #include <resolv.h> #include <cutils/list.h> #include <cutils/sockets.h> #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "fdevent.h" #include "mincrypt/rsa.h" #define TRACE_TAG TRACE_AUTH struct adb_public_key { struct listnode node; RSAPublicKey key; }; static struct listnode key_list; static char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", NULL }; static fdevent listener_fde; static int framework_fd = -1; static void read_keys(const char *file, struct listnode *list) { struct adb_public_key *key; FILE *f; char buf[MAX_PAYLOAD]; char *sep; int ret; f = fopen(file, "r"); if (!f) { D("Can't open '%s'\n", file); return; } while (fgets(buf, sizeof(buf), f)) { /* Allocate 4 extra bytes to decode the base64 data in-place */ key = calloc(1, sizeof(*key) + 4); if (!key) { D("Can't malloc key\n"); break; } sep = strpbrk(buf, " \t"); if (sep) *sep = '\0'; ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); if (ret != sizeof(key->key)) { D("%s: Invalid base64 data ret=%d\n", file, ret); free(key); continue; } if (key->key.len != RSANUMWORDS) { D("%s: Invalid key len %d\n", file, key->key.len); free(key); continue; } list_add_tail(list, &key->node); } fclose(f); } static void free_keys(struct listnode *list) { struct listnode *item; while (!list_empty(list)) { item = list_head(list); list_remove(item); free(node_to_item(item, struct adb_public_key, node)); } } void adb_auth_reload_keys(void) { char *path; char **paths = key_paths; struct stat buf; free_keys(&key_list); while ((path = *paths++)) { if (!stat(path, &buf)) { D("Loading keys from '%s'\n", path); read_keys(path, &key_list); } } } int adb_auth_generate_token(void *token, size_t token_size) { FILE *f; int ret; f = fopen("/dev/urandom", "r"); if (!f) return 0; ret = fread(token, token_size, 1, f); fclose(f); return ret * token_size; } int adb_auth_verify(void *token, void *sig, int siglen) { struct listnode *item; struct adb_public_key *key; int ret; if (siglen != RSANUMBYTES) return 0; list_for_each(item, &key_list) { key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(&key->key, sig, siglen, token); if (ret) return 1; } return 0; } static void adb_auth_event(int fd, unsigned events, void *data) { atransport *t = data; char response[2]; int ret; if (events & FDE_READ) { ret = unix_read(fd, response, sizeof(response)); if (ret < 0) { D("Disconnect"); fdevent_remove(&t->auth_fde); framework_fd = -1; } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { adb_auth_reload_keys(); adb_auth_verified(t); } } } void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) { char msg[MAX_PAYLOAD]; int ret; if (framework_fd < 0) { D("Client not connected\n"); return; } if (key[len - 1] != '\0') { D("Key must be a null-terminated string\n"); return; } ret = snprintf(msg, sizeof(msg), "PK%s", key); if (ret >= (signed)sizeof(msg)) { D("Key too long. ret=%d", ret); return; } D("Sending '%s'\n", msg); ret = unix_write(framework_fd, msg, ret); if (ret < 0) { D("Failed to write PK, errno=%d\n", errno); return; } fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); fdevent_add(&t->auth_fde, FDE_READ); } static void adb_auth_listener(int fd, unsigned events, void *data) { struct sockaddr addr; socklen_t alen; int s; alen = sizeof(addr); s = adb_socket_accept(fd, &addr, &alen); if (s < 0) { D("Failed to accept: errno=%d\n", errno); return; } framework_fd = s; } void adb_auth_init(void) { int fd, ret; list_init(&key_list); adb_auth_reload_keys(); fd = android_get_control_socket("adbd"); if (fd < 0) { D("Failed to get adbd socket\n"); return; } ret = listen(fd, 4); if (ret < 0) { D("Failed to listen on '%d'\n", fd); return; } fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); fdevent_add(&listener_fde, FDE_READ); } Loading
adb/Android.mk +16 −6 Original line number Diff line number Diff line Loading @@ -17,32 +17,34 @@ ifeq ($(HOST_OS),linux) USB_SRCS := usb_linux.c EXTRA_SRCS := get_my_path_linux.c LOCAL_LDLIBS += -lrt -lncurses -lpthread LOCAL_SHARED_LIBRARIES := libcrypto endif ifeq ($(HOST_OS),darwin) USB_SRCS := usb_osx.c EXTRA_SRCS := get_my_path_darwin.c LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon LOCAL_LDLIBS += -lpthread -lcrypto -framework CoreFoundation -framework IOKit -framework Carbon endif ifeq ($(HOST_OS),freebsd) USB_SRCS := usb_libusb.c EXTRA_SRCS := get_my_path_freebsd.c LOCAL_LDLIBS += -lpthread -lusb LOCAL_SHARED_LIBRARIES := libcrypto endif ifeq ($(HOST_OS),windows) USB_SRCS := usb_windows.c EXTRA_SRCS := get_my_path_windows.c EXTRA_STATIC_LIBS := AdbWinApi EXTRA_SRCS := get_my_path_windows.c ../libcutils/list.c EXTRA_STATIC_LIBS := AdbWinApi libcrypto_static ifneq ($(strip $(USE_CYGWIN)),) # Pure cygwin case LOCAL_LDLIBS += -lpthread LOCAL_LDLIBS += -lpthread -lgdi32 LOCAL_C_INCLUDES += /usr/include/w32api/ddk endif ifneq ($(strip $(USE_MINGW)),) # MinGW under Linux case LOCAL_LDLIBS += -lws2_32 LOCAL_LDLIBS += -lws2_32 -lgdi32 USE_SYSDEPS_WIN32 := 1 LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk endif Loading @@ -57,6 +59,7 @@ LOCAL_SRC_FILES := \ transport_usb.c \ commandline.c \ adb_client.c \ adb_auth_host.c \ sockets.c \ services.c \ file_sync_client.c \ Loading @@ -65,6 +68,7 @@ LOCAL_SRC_FILES := \ utils.c \ usb_vendors.c LOCAL_C_INCLUDES += external/openssl/include ifneq ($(USE_SYSDEPS_WIN32),) LOCAL_SRC_FILES += sysdeps_win32.c Loading Loading @@ -104,6 +108,7 @@ LOCAL_SRC_FILES := \ transport.c \ transport_local.c \ transport_usb.c \ adb_auth_client.c \ sockets.c \ services.c \ file_sync_service.c \ Loading @@ -127,7 +132,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) LOCAL_STATIC_LIBRARIES := libcutils libc LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt include $(BUILD_EXECUTABLE) Loading @@ -146,6 +151,7 @@ LOCAL_SRC_FILES := \ transport_usb.c \ commandline.c \ adb_client.c \ adb_auth_host.c \ sockets.c \ services.c \ file_sync_client.c \ Loading @@ -165,9 +171,13 @@ LOCAL_CFLAGS := \ -D_XOPEN_SOURCE \ -D_GNU_SOURCE LOCAL_C_INCLUDES += external/openssl/include LOCAL_MODULE := adb LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils LOCAL_SHARED_LIBRARIES := libcrypto include $(BUILD_EXECUTABLE) endif
adb/adb.c +114 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) Loading @@ -46,6 +47,8 @@ ADB_MUTEX_DEFINE( D_lock ); int HOST = 0; static int auth_enabled = 0; #if !ADB_HOST static const char *adb_device_banner = "device"; #endif Loading Loading @@ -100,6 +103,7 @@ void adb_trace_init(void) { "transport", TRACE_TRANSPORT }, { "jdwp", TRACE_JDWP }, { "services", TRACE_SERVICES }, { "auth", TRACE_AUTH }, { NULL, 0 } }; Loading Loading @@ -203,19 +207,21 @@ void put_apacket(apacket *p) free(p); } void handle_online(void) void handle_online(atransport *t) { D("adb: online\n"); t->online = 1; } void handle_offline(atransport *t) { D("adb: offline\n"); //Close the associated usb t->online = 0; run_transport_disconnects(t); } #if TRACE_PACKETS #if DEBUG_PACKETS #define DUMPMAX 32 void print_packet(const char *label, apacket *p) { Loading @@ -230,6 +236,7 @@ void print_packet(const char *label, apacket *p) case A_OKAY: tag = "OKAY"; break; case A_CLSE: tag = "CLSE"; break; case A_WRTE: tag = "WRTE"; break; case A_AUTH: tag = "AUTH"; break; default: tag = "????"; break; } Loading @@ -251,7 +258,7 @@ void print_packet(const char *label, apacket *p) } x++; } fprintf(stderr, tag); fputs(tag, stderr); } #endif Loading Loading @@ -315,11 +322,70 @@ static void send_connect(atransport *t) cp->msg.data_length = fill_connect_data((char *)cp->data, sizeof(cp->data)); send_packet(cp, t); #if ADB_HOST /* XXX why sleep here? */ // allow the device some time to respond to the connect message adb_sleep_ms(1000); #endif } static void send_auth_request(atransport *t) { D("Calling send_auth_request\n"); apacket *p; int ret; ret = adb_auth_generate_token(t->token, sizeof(t->token)); if (ret != sizeof(t->token)) { D("Error generating token ret=%d\n", ret); return; } p = get_apacket(); memcpy(p->data, t->token, ret); p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_TOKEN; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_response(uint8_t *token, size_t token_size, atransport *t) { D("Calling send_auth_response\n"); apacket *p = get_apacket(); int ret; ret = adb_auth_sign(t->key, token, token_size, p->data); if (!ret) { D("Error signing the token\n"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_publickey(atransport *t) { D("Calling send_auth_publickey\n"); apacket *p = get_apacket(); int ret; ret = adb_auth_get_userkey(p->data, sizeof(p->data)); if (!ret) { D("Failed to get user public key\n"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY; p->msg.data_length = ret; send_packet(p, t); } void adb_auth_verified(atransport *t) { handle_online(t); send_connect(t); } static char *connection_state_name(atransport *t) Loading Loading @@ -451,13 +517,42 @@ void handle_packet(apacket *p, atransport *t) t->connection_state = CS_OFFLINE; handle_offline(t); } parse_banner((char*) p->data, t); handle_online(); if (HOST || !auth_enabled) { handle_online(t); if(!HOST) send_connect(t); } else { send_auth_request(t); } break; case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { adb_auth_confirm_key(p->data, p->msg.data_length, t); } break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); Loading @@ -473,7 +568,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_OKAY: /* READY(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { if(s->peer == 0) { s->peer = create_remote_socket(p->msg.arg0, t); Loading @@ -485,7 +580,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_CLSE: /* CLOSE(local-id, remote-id, "") */ if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { s->close(s); } Loading @@ -493,7 +588,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_WRTE: if(t->connection_state != CS_OFFLINE) { if (t->online) { if((s = find_local_socket(p->msg.arg1))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; Loading Loading @@ -1014,6 +1109,7 @@ int adb_main(int is_daemon, int server_port) usb_vendors_init(); usb_init(); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); adb_auth_init(); char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); Loading @@ -1021,6 +1117,10 @@ int adb_main(int is_daemon, int server_port) exit(1); } #else property_get("ro.adb.secure", value, "0"); auth_enabled = !strcmp(value, "1"); if (auth_enabled) adb_auth_init(); /* don't listen on a port (default 5037) if running in secure mode */ /* don't run as root if we are running in secure mode */ Loading
adb/adb.h +12 −2 Original line number Diff line number Diff line Loading @@ -29,13 +29,14 @@ #define A_OKAY 0x59414b4f #define A_CLSE 0x45534c43 #define A_WRTE 0x45545257 #define A_AUTH 0x48545541 #define A_VERSION 0x01000000 // ADB protocol version #define ADB_VERSION_MAJOR 1 // Used for help/version information #define ADB_VERSION_MINOR 0 // Used for help/version information #define ADB_SERVER_VERSION 29 // Increment this when we want to force users to start a new adb server #define ADB_SERVER_VERSION 30 // Increment this when we want to force users to start a new adb server typedef struct amessage amessage; typedef struct apacket apacket; Loading Loading @@ -165,6 +166,8 @@ typedef enum transport_type { kTransportHost, } transport_type; #define TOKEN_SIZE 20 struct atransport { atransport *next; Loading @@ -181,6 +184,7 @@ struct atransport int ref_count; unsigned sync_token; int connection_state; int online; transport_type type; /* usb handle or socket fd as needed */ Loading @@ -198,6 +202,11 @@ struct atransport /* a list of adisconnect callbacks called when the transport is kicked */ int kicked; adisconnect disconnects; void *key; unsigned char token[TOKEN_SIZE]; fdevent auth_fde; unsigned failed_auth_attempts; }; Loading Loading @@ -349,6 +358,7 @@ typedef enum { TRACE_SYSDEPS, TRACE_JDWP, /* 0x100 */ TRACE_SERVICES, TRACE_AUTH, } AdbTrace; #if ADB_TRACE Loading Loading @@ -408,7 +418,7 @@ void adb_qemu_trace(const char* fmt, ...); #endif #if !TRACE_PACKETS #if !DEBUG_PACKETS #define print_packet(tag,p) do {} while (0) #endif Loading
adb/adb_auth.h 0 → 100644 +54 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 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. */ #ifndef __ADB_AUTH_H #define __ADB_AUTH_H void adb_auth_init(void); void adb_auth_verified(atransport *t); /* AUTH packets first argument */ /* Request */ #define ADB_AUTH_TOKEN 1 /* Response */ #define ADB_AUTH_SIGNATURE 2 #define ADB_AUTH_RSAPUBLICKEY 3 #if ADB_HOST int adb_auth_sign(void *key, void *token, size_t token_size, void *sig); void *adb_auth_nextkey(void *current); int adb_auth_get_userkey(unsigned char *data, size_t len); static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; } static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { } static inline void adb_auth_reload_keys(void) { } #else // !ADB_HOST static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; } static inline void *adb_auth_nextkey(void *current) { return NULL; } static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; } int adb_auth_generate_token(void *token, size_t token_size); int adb_auth_verify(void *token, void *sig, int siglen); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); void adb_auth_reload_keys(void); #endif // ADB_HOST #endif // __ADB_AUTH_H
adb/adb_auth_client.c 0 → 100644 +245 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 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 <stdio.h> #include <string.h> #include <resolv.h> #include <cutils/list.h> #include <cutils/sockets.h> #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "fdevent.h" #include "mincrypt/rsa.h" #define TRACE_TAG TRACE_AUTH struct adb_public_key { struct listnode node; RSAPublicKey key; }; static struct listnode key_list; static char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", NULL }; static fdevent listener_fde; static int framework_fd = -1; static void read_keys(const char *file, struct listnode *list) { struct adb_public_key *key; FILE *f; char buf[MAX_PAYLOAD]; char *sep; int ret; f = fopen(file, "r"); if (!f) { D("Can't open '%s'\n", file); return; } while (fgets(buf, sizeof(buf), f)) { /* Allocate 4 extra bytes to decode the base64 data in-place */ key = calloc(1, sizeof(*key) + 4); if (!key) { D("Can't malloc key\n"); break; } sep = strpbrk(buf, " \t"); if (sep) *sep = '\0'; ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); if (ret != sizeof(key->key)) { D("%s: Invalid base64 data ret=%d\n", file, ret); free(key); continue; } if (key->key.len != RSANUMWORDS) { D("%s: Invalid key len %d\n", file, key->key.len); free(key); continue; } list_add_tail(list, &key->node); } fclose(f); } static void free_keys(struct listnode *list) { struct listnode *item; while (!list_empty(list)) { item = list_head(list); list_remove(item); free(node_to_item(item, struct adb_public_key, node)); } } void adb_auth_reload_keys(void) { char *path; char **paths = key_paths; struct stat buf; free_keys(&key_list); while ((path = *paths++)) { if (!stat(path, &buf)) { D("Loading keys from '%s'\n", path); read_keys(path, &key_list); } } } int adb_auth_generate_token(void *token, size_t token_size) { FILE *f; int ret; f = fopen("/dev/urandom", "r"); if (!f) return 0; ret = fread(token, token_size, 1, f); fclose(f); return ret * token_size; } int adb_auth_verify(void *token, void *sig, int siglen) { struct listnode *item; struct adb_public_key *key; int ret; if (siglen != RSANUMBYTES) return 0; list_for_each(item, &key_list) { key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(&key->key, sig, siglen, token); if (ret) return 1; } return 0; } static void adb_auth_event(int fd, unsigned events, void *data) { atransport *t = data; char response[2]; int ret; if (events & FDE_READ) { ret = unix_read(fd, response, sizeof(response)); if (ret < 0) { D("Disconnect"); fdevent_remove(&t->auth_fde); framework_fd = -1; } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { adb_auth_reload_keys(); adb_auth_verified(t); } } } void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) { char msg[MAX_PAYLOAD]; int ret; if (framework_fd < 0) { D("Client not connected\n"); return; } if (key[len - 1] != '\0') { D("Key must be a null-terminated string\n"); return; } ret = snprintf(msg, sizeof(msg), "PK%s", key); if (ret >= (signed)sizeof(msg)) { D("Key too long. ret=%d", ret); return; } D("Sending '%s'\n", msg); ret = unix_write(framework_fd, msg, ret); if (ret < 0) { D("Failed to write PK, errno=%d\n", errno); return; } fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); fdevent_add(&t->auth_fde, FDE_READ); } static void adb_auth_listener(int fd, unsigned events, void *data) { struct sockaddr addr; socklen_t alen; int s; alen = sizeof(addr); s = adb_socket_accept(fd, &addr, &alen); if (s < 0) { D("Failed to accept: errno=%d\n", errno); return; } framework_fd = s; } void adb_auth_init(void) { int fd, ret; list_init(&key_list); adb_auth_reload_keys(); fd = android_get_control_socket("adbd"); if (fd < 0) { D("Failed to get adbd socket\n"); return; } ret = listen(fd, 4); if (ret < 0) { D("Failed to listen on '%d'\n", fd); return; } fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); fdevent_add(&listener_fde, FDE_READ); }