Implement SID API

Change-Id: Id11632a6b4b9cab6f08f97026dd65fdf49a46491
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk
index 1953672..f743cc3 100644
--- a/gatekeeperd/Android.mk
+++ b/gatekeeperd/Android.mk
@@ -26,4 +26,6 @@
 	libhardware \
 	libutils \
 	libkeystore_binder
+LOCAL_C_INCLUDES := \
+	system/gatekeeper/include
 include $(BUILD_EXECUTABLE)
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
index b1e4811..d4ed533 100644
--- a/gatekeeperd/IGateKeeperService.cpp
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -115,6 +115,14 @@
             }
             return NO_ERROR;
         }
+        case GET_SECURE_USER_ID: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+            uint64_t sid = getSecureUserId(uid);
+            reply->writeNoException();
+            reply->writeInt64(sid);
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/gatekeeperd/IGateKeeperService.h b/gatekeeperd/IGateKeeperService.h
index 10b1b43..51e179d 100644
--- a/gatekeeperd/IGateKeeperService.h
+++ b/gatekeeperd/IGateKeeperService.h
@@ -31,6 +31,7 @@
         ENROLL = IBinder::FIRST_CALL_TRANSACTION + 0,
         VERIFY = IBinder::FIRST_CALL_TRANSACTION + 1,
         VERIFY_CHALLENGE = IBinder::FIRST_CALL_TRANSACTION + 2,
+        GET_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 3,
     };
 
     // DECLARE_META_INTERFACE - C++ client interface not needed
@@ -64,6 +65,11 @@
             const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
             const uint8_t *provided_password, uint32_t provided_password_length,
             uint8_t **auth_token, uint32_t *auth_token_length) = 0;
+
+    /**
+     * Returns the secure user ID for the provided android user
+     */
+    virtual uint64_t getSecureUserId(uint32_t uid) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index d59e6fe..82aa422 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -18,6 +18,12 @@
 
 #include "IGateKeeperService.h"
 
+#include <errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <unistd.h>
+
 #include <cutils/log.h>
 #include <utils/Log.h>
 
@@ -28,7 +34,9 @@
 
 #include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // For error code
+#include <gatekeeper/password_handle.h> // for password_handle_t
 #include <hardware/gatekeeper.h>
+#include <hardware/hw_auth_token.h>
 
 namespace android {
 
@@ -50,6 +58,36 @@
         gatekeeper_close(device);
     }
 
+    void store_sid(uint32_t uid, uint64_t sid) {
+        char filename[21];
+        sprintf(filename, "%u", uid);
+        int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+        if (fd < 0) {
+            ALOGW("could not open file: %s: %s", filename, strerror(errno));
+            return;
+        }
+        write(fd, &sid, sizeof(sid));
+        close(fd);
+    }
+
+    void maybe_store_sid(uint32_t uid, uint64_t sid) {
+        char filename[21];
+        sprintf(filename, "%u", uid);
+        if (access(filename, F_OK) == -1) {
+            store_sid(uid, sid);
+        }
+    }
+
+    uint64_t read_sid(uint32_t uid) {
+        char filename[21];
+        uint64_t sid;
+        sprintf(filename, "%u", uid);
+        int fd = open(filename, O_RDONLY);
+        if (fd < 0) return 0;
+        read(fd, &sid, sizeof(sid));
+        return sid;
+    }
+
     virtual status_t enroll(uint32_t uid,
             const uint8_t *current_password_handle, uint32_t current_password_handle_length,
             const uint8_t *current_password, uint32_t current_password_length,
@@ -69,7 +107,13 @@
                 current_password, current_password_length,
                 desired_password, desired_password_length,
                 enrolled_password_handle, enrolled_password_handle_length);
-        return ret >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+        if (ret >= 0) {
+            gatekeeper::password_handle_t *handle =
+                    reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
+            store_sid(uid, handle->user_id);
+            return NO_ERROR;
+        }
+        return UNKNOWN_ERROR;
     }
 
     virtual status_t verify(uint32_t uid,
@@ -116,7 +160,17 @@
             }
         }
 
-        return ret >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+        if (ret >= 0) {
+            maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
+                        enrolled_password_handle)->user_id);
+            return NO_ERROR;
+        }
+
+        return UNKNOWN_ERROR;
+    }
+
+    virtual uint64_t getSecureUserId(uint32_t uid) {
+        return read_sid(uid);
     }
 
     virtual status_t dump(int fd, const Vector<String16> &) {
@@ -144,8 +198,17 @@
 };
 }// namespace android
 
-int main() {
+int main(int argc, char* argv[]) {
     ALOGI("Starting gatekeeperd...");
+    if (argc < 2) {
+        ALOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+
     android::sp<android::IServiceManager> sm = android::defaultServiceManager();
     android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
     android::status_t ret = sm->addService(
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 86b769f..ac6818a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -254,6 +254,7 @@
     mkdir /data/misc/bluedroid 0770 bluetooth net_bt_stack
     mkdir /data/misc/bluetooth 0770 system system
     mkdir /data/misc/keystore 0700 keystore keystore
+    mkdir /data/misc/gatekeeper 0700 system system
     mkdir /data/misc/keychain 0771 system system
     mkdir /data/misc/net 0750 root shell
     mkdir /data/misc/radio 0770 system radio
@@ -608,7 +609,7 @@
     disabled
     oneshot
 
-service gatekeeperd /system/bin/gatekeeperd
+service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper
     class main
     user system