Merge change 24673 into eclair
* changes: Add tests and misc fixes on keystore.
This commit is contained in:
@@ -4,7 +4,7 @@ LOCAL_PATH:= $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
netkeystore.c keymgmt.c
|
netkeystore.c netkeystore_main.c keymgmt.c
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := \
|
LOCAL_C_INCLUDES := \
|
||||||
$(call include-path-for, system-core)/cutils \
|
$(call include-path-for, system-core)/cutils \
|
||||||
|
|||||||
@@ -385,7 +385,10 @@ int reset_keystore()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while ((de = readdir(d))) {
|
while ((de = readdir(d))) {
|
||||||
if (unlink(de->d_name) != 0) ret = -1;
|
char *dirname = de->d_name;
|
||||||
|
if (strcmp(".", dirname) == 0) continue;
|
||||||
|
if (strcmp("..", dirname) == 0) continue;
|
||||||
|
if (unlink(dirname) != 0) ret = -1;
|
||||||
}
|
}
|
||||||
closedir(d);
|
closedir(d);
|
||||||
state = UNINITIALIZED;
|
state = UNINITIALIZED;
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LOG_TAG "keystore"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -247,7 +245,7 @@ static void do_reset_keystore(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
|
|||||||
reply->retcode = reset_keystore();
|
reply->retcode = reset_keystore();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
|
void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
|
||||||
{
|
{
|
||||||
uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
|
uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
|
||||||
|
|
||||||
@@ -309,7 +307,7 @@ static int flatten_str_args(int argc, const char **argv, LPC_MARSHAL *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
|
int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
|
||||||
{
|
{
|
||||||
uint32_t i, len = 0;
|
uint32_t i, len = 0;
|
||||||
uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
|
uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
|
||||||
@@ -335,30 +333,30 @@ static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shell_command(const int argc, const char **argv)
|
int shell_command(const int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
LPC_MARSHAL cmd;
|
LPC_MARSHAL cmd;
|
||||||
|
|
||||||
if (parse_cmd(argc, argv , &cmd)) {
|
if (parse_cmd(argc, argv, &cmd)) {
|
||||||
fprintf(stderr, "Incorrect command or command line is too long.\n");
|
fprintf(stderr, "Incorrect command or command line is too long.\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
fd = socket_local_client(SOCKET_PATH,
|
fd = socket_local_client(SOCKET_PATH,
|
||||||
ANDROID_SOCKET_NAMESPACE_RESERVED,
|
ANDROID_SOCKET_NAMESPACE_RESERVED,
|
||||||
SOCK_STREAM);
|
SOCK_STREAM);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fprintf(stderr, "Keystore service is not up and running.\n");
|
fprintf(stderr, "Keystore service is not up and running.\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_marshal(fd, &cmd)) {
|
if (write_marshal(fd, &cmd)) {
|
||||||
fprintf(stderr, "Incorrect command or command line is too long.\n");
|
fprintf(stderr, "Incorrect command or command line is too long.\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
if (read_marshal(fd, &cmd)) {
|
if (read_marshal(fd, &cmd)) {
|
||||||
fprintf(stderr, "Failed to read the result.\n");
|
fprintf(stderr, "Failed to read the result.\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
cmd.data[cmd.len] = 0;
|
cmd.data[cmd.len] = 0;
|
||||||
fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
|
fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
|
||||||
@@ -367,30 +365,26 @@ static int shell_command(const int argc, const char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(const int argc, const char *argv[])
|
int server_main(const int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
struct sockaddr addr;
|
struct sockaddr addr;
|
||||||
socklen_t alen;
|
socklen_t alen;
|
||||||
int lsocket, s;
|
int lsocket, s;
|
||||||
LPC_MARSHAL cmd, reply;
|
LPC_MARSHAL cmd, reply;
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
return shell_command(argc - 1, argv + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init_keystore(KEYSTORE_DIR)) {
|
if (init_keystore(KEYSTORE_DIR)) {
|
||||||
LOGE("Can not initialize the keystore, the directory exist?\n");
|
LOGE("Can not initialize the keystore, the directory exist?\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsocket = android_get_control_socket(SOCKET_PATH);
|
lsocket = android_get_control_socket(SOCKET_PATH);
|
||||||
if (lsocket < 0) {
|
if (lsocket < 0) {
|
||||||
LOGE("Failed to get socket from environment: %s\n", strerror(errno));
|
LOGE("Failed to get socket from environment: %s\n", strerror(errno));
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
if (listen(lsocket, 5)) {
|
if (listen(lsocket, 5)) {
|
||||||
LOGE("Listen on socket failed: %s\n", strerror(errno));
|
LOGE("Listen on socket failed: %s\n", strerror(errno));
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
|
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
|
||||||
memset(&reply, 0, sizeof(LPC_MARSHAL));
|
memset(&reply, 0, sizeof(LPC_MARSHAL));
|
||||||
|
|||||||
@@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
// for testing
|
||||||
|
int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd);
|
||||||
|
void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
|
||||||
|
|
||||||
static inline int readx(int s, void *_buf, int count)
|
static inline int readx(int s, void *_buf, int count)
|
||||||
{
|
{
|
||||||
char *buf = _buf;
|
char *buf = _buf;
|
||||||
|
|||||||
29
cmds/keystore/netkeystore_main.c
Normal file
29
cmds/keystore/netkeystore_main.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
** Copyright 2009, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "keystore"
|
||||||
|
|
||||||
|
int shell_command(const int argc, const char **argv);
|
||||||
|
int server_main(const int argc, const char *argv[]);
|
||||||
|
|
||||||
|
int main(const int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
if (argc > 1) {
|
||||||
|
return shell_command(argc - 1, argv + 1);
|
||||||
|
} else {
|
||||||
|
return server_main(argc, argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
ifdef KEYSTORE_TESTS
|
ifdef KEYSTORE_TESTS
|
||||||
LOCAL_PATH:= $(call my-dir)
|
LOCAL_PATH:= $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
|
LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c ../netkeystore.c
|
||||||
LOCAL_SHARED_LIBRARIES := libcutils libssl
|
LOCAL_SHARED_LIBRARIES := libcutils libssl
|
||||||
LOCAL_MODULE:= netkeystore_test
|
LOCAL_MODULE:= netkeystore_test
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
|||||||
@@ -29,9 +29,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <cutils/log.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "keymgmt.h"
|
#include "keymgmt.h"
|
||||||
|
#include "netkeystore.h"
|
||||||
|
|
||||||
|
#define LOG_TAG "keystore_test"
|
||||||
|
|
||||||
typedef int FUNC_PTR();
|
typedef int FUNC_PTR();
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -61,7 +65,9 @@ void setup()
|
|||||||
|
|
||||||
void teardown()
|
void teardown()
|
||||||
{
|
{
|
||||||
reset_keystore();
|
if (reset_keystore() != 0) {
|
||||||
|
fprintf(stderr, "Can not reset the test directory %s\n", TEST_DIR);
|
||||||
|
}
|
||||||
rmdir(TEST_DIR);
|
rmdir(TEST_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +80,7 @@ FUNC_BODY(init_keystore)
|
|||||||
|
|
||||||
FUNC_BODY(reset_keystore)
|
FUNC_BODY(reset_keystore)
|
||||||
{
|
{
|
||||||
chdir("/procx");
|
int ret = chdir("/proc");
|
||||||
if (reset_keystore() == 0) return -1;
|
if (reset_keystore() == 0) return -1;
|
||||||
chdir(TEST_DIR);
|
chdir(TEST_DIR);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
@@ -87,7 +93,8 @@ FUNC_BODY(get_state)
|
|||||||
if (get_state() != UNLOCKED) return -1;
|
if (get_state() != UNLOCKED) return -1;
|
||||||
lock();
|
lock();
|
||||||
if (get_state() != LOCKED) return -1;
|
if (get_state() != LOCKED) return -1;
|
||||||
reset_keystore();
|
|
||||||
|
if (reset_keystore() != 0) return -1;
|
||||||
if (get_state() != UNINITIALIZED) return -1;
|
if (get_state() != UNINITIALIZED) return -1;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -218,6 +225,37 @@ FUNC_BODY(list_keys)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int execute_cmd(int argc, const char *argv[], LPC_MARSHAL *cmd,
|
||||||
|
LPC_MARSHAL *reply)
|
||||||
|
{
|
||||||
|
memset(cmd, 0, sizeof(LPC_MARSHAL));
|
||||||
|
memset(reply, 0, sizeof(LPC_MARSHAL));
|
||||||
|
if (parse_cmd(argc, argv, cmd)) return -1;
|
||||||
|
execute(cmd, reply);
|
||||||
|
return (reply->retcode ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNC_BODY(client_passwd)
|
||||||
|
{
|
||||||
|
LPC_MARSHAL cmd, reply;
|
||||||
|
const char *set_passwd_cmds[2] = {"passwd", TEST_PASSWD};
|
||||||
|
const char *change_passwd_cmds[3] = {"passwd", TEST_PASSWD, TEST_NPASSWD};
|
||||||
|
|
||||||
|
if (execute_cmd(2, set_passwd_cmds, &cmd, &reply)) return -1;
|
||||||
|
|
||||||
|
lock();
|
||||||
|
if (unlock("55555555") == 0) return -1;
|
||||||
|
if (unlock(TEST_PASSWD) != 0) return -1;
|
||||||
|
|
||||||
|
if (execute_cmd(3, change_passwd_cmds, &cmd, &reply)) return -1;
|
||||||
|
|
||||||
|
lock();
|
||||||
|
if (unlock(TEST_PASSWD) == 0) return -1;
|
||||||
|
if (unlock(TEST_NPASSWD) != 0) return -1;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
TESTFUNC all_tests[] = {
|
TESTFUNC all_tests[] = {
|
||||||
FUNC_NAME(init_keystore),
|
FUNC_NAME(init_keystore),
|
||||||
FUNC_NAME(reset_keystore),
|
FUNC_NAME(reset_keystore),
|
||||||
@@ -229,11 +267,13 @@ TESTFUNC all_tests[] = {
|
|||||||
FUNC_NAME(get_key),
|
FUNC_NAME(get_key),
|
||||||
FUNC_NAME(remove_key),
|
FUNC_NAME(remove_key),
|
||||||
FUNC_NAME(list_keys),
|
FUNC_NAME(list_keys),
|
||||||
|
FUNC_NAME(client_passwd),
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int i, ret;
|
int i, ret;
|
||||||
for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
|
for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
|
||||||
|
LOGD("run %s...\n", all_tests[i].name);
|
||||||
setup();
|
setup();
|
||||||
if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
|
if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
|
||||||
fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
|
fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public abstract class Keystore {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lock() {
|
public int lock() {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.LOCK, null);
|
Reply result = mServiceCommand.execute(ServiceCommand.LOCK);
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,15 +73,14 @@ public abstract class Keystore {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getState() {
|
public int getState() {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.GET_STATE,
|
Reply result = mServiceCommand.execute(ServiceCommand.GET_STATE);
|
||||||
null);
|
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int changePassword(String oldPassword, String newPassword) {
|
public int changePassword(String oldPassword, String newPassword) {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.PASSWD,
|
Reply result = mServiceCommand.execute(ServiceCommand.PASSWD,
|
||||||
oldPassword + "\0" + newPassword + "\0");
|
oldPassword, newPassword);
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,14 +105,14 @@ public abstract class Keystore {
|
|||||||
@Override
|
@Override
|
||||||
public int put(String namespace, String keyname, String value) {
|
public int put(String namespace, String keyname, String value) {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.PUT_KEY,
|
Reply result = mServiceCommand.execute(ServiceCommand.PUT_KEY,
|
||||||
namespace + "\0" + keyname + "\0" + value);
|
namespace, keyname, value);
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(String namespace, String keyname) {
|
public String get(String namespace, String keyname) {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.GET_KEY,
|
Reply result = mServiceCommand.execute(ServiceCommand.GET_KEY,
|
||||||
namespace + "\0" + keyname + "\0");
|
namespace, keyname);
|
||||||
return (result != null) ? ((result.returnCode != 0) ? null :
|
return (result != null) ? ((result.returnCode != 0) ? null :
|
||||||
new String(result.data, 0, result.len)) : null;
|
new String(result.data, 0, result.len)) : null;
|
||||||
}
|
}
|
||||||
@@ -121,13 +120,13 @@ public abstract class Keystore {
|
|||||||
@Override
|
@Override
|
||||||
public int remove(String namespace, String keyname) {
|
public int remove(String namespace, String keyname) {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.REMOVE_KEY,
|
Reply result = mServiceCommand.execute(ServiceCommand.REMOVE_KEY,
|
||||||
namespace + "\0" + keyname + "\0");
|
namespace, keyname);
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int reset() {
|
public int reset() {
|
||||||
Reply result = mServiceCommand.execute(ServiceCommand.RESET, null);
|
Reply result = mServiceCommand.execute(ServiceCommand.RESET);
|
||||||
return (result != null) ? result.returnCode : -1;
|
return (result != null) ? result.returnCode : -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,10 +141,18 @@ public class ServiceCommand {
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean writeCommand(int cmd, String _data) {
|
private byte[] convert(String... data) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (data.length >=1) sb.append(data[0]).append("\0");
|
||||||
|
if (data.length >=2) sb.append(data[1]).append("\0");
|
||||||
|
if (data.length >=3) sb.append(data[2]);
|
||||||
|
return sb.toString().getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeCommand(int cmd, String... data) {
|
||||||
byte buf[] = new byte[8];
|
byte buf[] = new byte[8];
|
||||||
byte[] data = (_data == null) ? new byte[0] : _data.getBytes();
|
byte[] dataBytes = convert(data);
|
||||||
int len = data.length;
|
int len = dataBytes.length;
|
||||||
// the length of data
|
// the length of data
|
||||||
buf[0] = (byte) ((len >> 24) & 0xff);
|
buf[0] = (byte) ((len >> 24) & 0xff);
|
||||||
buf[1] = (byte) ((len >> 16) & 0xff);
|
buf[1] = (byte) ((len >> 16) & 0xff);
|
||||||
@@ -157,7 +165,7 @@ public class ServiceCommand {
|
|||||||
buf[7] = (byte) (cmd & 0xff);
|
buf[7] = (byte) (cmd & 0xff);
|
||||||
try {
|
try {
|
||||||
mOut.write(buf, 0, 8);
|
mOut.write(buf, 0, 8);
|
||||||
mOut.write(data, 0, len);
|
mOut.write(dataBytes, 0, len);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.e(mTag,"write error", ex);
|
Log.e(mTag,"write error", ex);
|
||||||
disconnect();
|
disconnect();
|
||||||
@@ -166,7 +174,7 @@ public class ServiceCommand {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Reply executeCommand(int cmd, String data) {
|
private Reply executeCommand(int cmd, String... data) {
|
||||||
if (!writeCommand(cmd, data)) {
|
if (!writeCommand(cmd, data)) {
|
||||||
/* If service died and restarted in the background
|
/* If service died and restarted in the background
|
||||||
* (unlikely but possible) we'll fail on the next
|
* (unlikely but possible) we'll fail on the next
|
||||||
@@ -181,7 +189,7 @@ public class ServiceCommand {
|
|||||||
return readReply();
|
return readReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Reply execute(int cmd, String data) {
|
public synchronized Reply execute(int cmd, String... data) {
|
||||||
Reply result;
|
Reply result;
|
||||||
if (!connect()) {
|
if (!connect()) {
|
||||||
Log.e(mTag, "connection failed");
|
Log.e(mTag, "connection failed");
|
||||||
|
|||||||
Reference in New Issue
Block a user