/*
 * 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.
 */

#define LOG_TAG "SELinuxJNI"
#include <utils/Log.h>

#include <nativehelper/JNIHelp.h>
#include "jni.h"
#include "core_jni_helpers.h"
#include "selinux/selinux.h"
#include "selinux/android.h"
#include <errno.h>
#include <memory>
#include <atomic>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedUtfChars.h>

namespace android {
namespace {
std::atomic<selabel_handle*> sehandle{nullptr};

selabel_handle* GetSELabelHandle() {
    selabel_handle* h = sehandle.load();
    if (h != nullptr) {
        return h;
    }

    h = selinux_android_file_context_handle();
    selabel_handle* expected = nullptr;
    if (!sehandle.compare_exchange_strong(expected, h)) {
        selabel_close(h);
        return sehandle.load();
    }
    return h;
}

}

struct SecurityContext_Delete {
    void operator()(security_context_t p) const {
        freecon(p);
    }
};
typedef std::unique_ptr<char[], SecurityContext_Delete> Unique_SecurityContext;

static jboolean isSELinuxDisabled = true;

/*
 * Function: isSELinuxEnabled
 * Purpose:  checks whether SELinux is enabled/disbaled
 * Parameters: none
 * Return value : true (enabled) or false (disabled)
 * Exceptions: none
 */
static jboolean isSELinuxEnabled(JNIEnv *env, jobject) {
    return !isSELinuxDisabled;
}

/*
 * Function: isSELinuxEnforced
 * Purpose: return the current SELinux enforce mode
 * Parameters: none
 * Return value: true (enforcing) or false (permissive)
 * Exceptions: none
 */
static jboolean isSELinuxEnforced(JNIEnv *env, jobject) {
    return (security_getenforce() == 1) ? true : false;
}

static jstring fileSelabelLookup(JNIEnv* env, jobject, jstring pathStr) {
    if (isSELinuxDisabled) {
        ALOGE("fileSelabelLookup => SELinux is disabled");
        return NULL;
    }

    if (pathStr == NULL) {
      ALOGE("fileSelabelLookup => got null path.");
      jniThrowNullPointerException(
          env, "Trying to get security context of a null path.");
      return NULL;
    }

    ScopedUtfChars path(env, pathStr);
    const char* path_c_str = path.c_str();
    if (path_c_str == NULL) {
        ALOGE("fileSelabelLookup => Got null path");
        jniThrowNullPointerException(
            env, "Trying to get security context of a null path.");
        return NULL;
    }

    auto* selabel_handle = GetSELabelHandle();
    if (selabel_handle == NULL) {
        ALOGE("fileSelabelLookup => Failed to get SEHandle");
        return NULL;
    }

    security_context_t tmp = NULL;
    if (selabel_lookup(selabel_handle, &tmp, path_c_str, S_IFREG) != 0) {
      ALOGE("fileSelabelLookup => selabel_lookup for %s failed: %d", path_c_str, errno);
      return NULL;
    }

    Unique_SecurityContext context(tmp);
    return env->NewStringUTF(context.get());
}

static jstring getFdConInner(JNIEnv *env, jobject fileDescriptor, bool isSocket) {
    if (isSELinuxDisabled) {
        return NULL;
    }

    if (fileDescriptor == NULL) {
        jniThrowNullPointerException(env,
                "Trying to check security context of a null FileDescriptor.");
        return NULL;
    }

    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    if (env->ExceptionCheck()) {
        ALOGE("getFdCon => getFD for %p failed", fileDescriptor);
        return NULL;
    }

    security_context_t tmp = NULL;
    int ret;
    if (isSocket) {
        ret = getpeercon(fd, &tmp);
    } else{
        ret = fgetfilecon(fd, &tmp);
    }
    Unique_SecurityContext context(tmp);

    ScopedLocalRef<jstring> contextStr(env, NULL);
    if (ret != -1) {
        contextStr.reset(env->NewStringUTF(context.get()));
    }

    ALOGV("getFdCon(%d) => %s", fd, context.get());
    return contextStr.release();
}

/*
 * Function: getPeerCon
 * Purpose: retrieves security context of peer socket
 * Parameters:
 *        fileDescriptor: peer socket file as a FileDescriptor object
 * Returns: jstring representing the security_context of socket or NULL if error
 * Exceptions: NullPointerException if fileDescriptor object is NULL
 */
static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) {
    return getFdConInner(env, fileDescriptor, true);
}

/*
 * Function: getFdCon
 * Purpose: retrieves security context of a file descriptor.
 * Parameters:
 *        fileDescriptor: a FileDescriptor object
 * Returns: jstring representing the security_context of socket or NULL if error
 * Exceptions: NullPointerException if fileDescriptor object is NULL
 */
static jstring getFdCon(JNIEnv *env, jobject, jobject fileDescriptor) {
    return getFdConInner(env, fileDescriptor, false);
}

/*
 * Function: setFSCreateCon
 * Purpose: set security context used for creating a new file system object
 * Parameters:
 *       context: security_context_t representing the new context of a file system object,
 *                set to NULL to return to the default policy behavior
 * Returns: true on success, false on error
 * Exception: none
 */
static jboolean setFSCreateCon(JNIEnv *env, jobject, jstring contextStr) {
    if (isSELinuxDisabled) {
        return false;
    }

    std::unique_ptr<ScopedUtfChars> context;
    const char* context_c_str = NULL;
    if (contextStr != NULL) {
        context.reset(new ScopedUtfChars(env, contextStr));
        context_c_str = context->c_str();
        if (context_c_str == NULL) {
            return false;
        }
    }

    int ret = setfscreatecon(const_cast<char *>(context_c_str));

    ALOGV("setFSCreateCon(%s) => %d", context_c_str, ret);

    return (ret == 0) ? true : false;
}

/*
 * Function: setFileCon
 * Purpose:  set the security context of a file object
 * Parameters:
 *       path: the location of the file system object
 *       context: the new security context of the file system object
 * Returns: true on success, false on error
 * Exception: NullPointerException is thrown if either path or context strign are NULL
 */
static jboolean setFileCon(JNIEnv *env, jobject, jstring pathStr, jstring contextStr) {
    if (isSELinuxDisabled) {
        return false;
    }

    ScopedUtfChars path(env, pathStr);
    if (path.c_str() == NULL) {
        return false;
    }

    ScopedUtfChars context(env, contextStr);
    if (context.c_str() == NULL) {
        return false;
    }

    // GetStringUTFChars returns const char * yet setfilecon needs char *
    char *tmp = const_cast<char *>(context.c_str());
    int ret = setfilecon(path.c_str(), tmp);

    ALOGV("setFileCon(%s, %s) => %d", path.c_str(), context.c_str(), ret);
    return (ret == 0) ? true : false;
}

/*
 * Function: getFileCon
 * Purpose: retrieves the context associated with the given path in the file system
 * Parameters:
 *        path: given path in the file system
 * Returns:
 *        string representing the security context string of the file object
 *        the string may be NULL if an error occured
 * Exceptions: NullPointerException if the path object is null
 */
static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) {
    if (isSELinuxDisabled) {
        return NULL;
    }

    ScopedUtfChars path(env, pathStr);
    if (path.c_str() == NULL) {
        return NULL;
    }

    security_context_t tmp = NULL;
    int ret = getfilecon(path.c_str(), &tmp);
    Unique_SecurityContext context(tmp);

    ScopedLocalRef<jstring> securityString(env, NULL);
    if (ret != -1) {
        securityString.reset(env->NewStringUTF(context.get()));
    }

    ALOGV("getFileCon(%s) => %s", path.c_str(), context.get());
    return securityString.release();
}

/*
 * Function: getCon
 * Purpose: Get the context of the current process.
 * Parameters: none
 * Returns: a jstring representing the security context of the process,
 *          the jstring may be NULL if there was an error
 * Exceptions: none
 */
static jstring getCon(JNIEnv *env, jobject) {
    if (isSELinuxDisabled) {
        return NULL;
    }

    security_context_t tmp = NULL;
    int ret = getcon(&tmp);
    Unique_SecurityContext context(tmp);

    ScopedLocalRef<jstring> securityString(env, NULL);
    if (ret != -1) {
        securityString.reset(env->NewStringUTF(context.get()));
    }

    ALOGV("getCon() => %s", context.get());
    return securityString.release();
}

/*
 * Function: getPidCon
 * Purpose: Get the context of a process identified by its pid
 * Parameters:
 *            pid: a jint representing the process
 * Returns: a jstring representing the security context of the pid,
 *          the jstring may be NULL if there was an error
 * Exceptions: none
 */
static jstring getPidCon(JNIEnv *env, jobject, jint pid) {
    if (isSELinuxDisabled) {
        return NULL;
    }

    security_context_t tmp = NULL;
    int ret = getpidcon(static_cast<pid_t>(pid), &tmp);
    Unique_SecurityContext context(tmp);

    ScopedLocalRef<jstring> securityString(env, NULL);
    if (ret != -1) {
        securityString.reset(env->NewStringUTF(context.get()));
    }

    ALOGV("getPidCon(%d) => %s", pid, context.get());
    return securityString.release();
}

/*
 * Function: checkSELinuxAccess
 * Purpose: Check permissions between two security contexts.
 * Parameters: subjectContextStr: subject security context as a string
 *             objectContextStr: object security context as a string
 *             objectClassStr: object's security class name as a string
 *             permissionStr: permission name as a string
 * Returns: boolean: (true) if permission was granted, (false) otherwise
 * Exceptions: None
 */
static jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextStr,
        jstring objectContextStr, jstring objectClassStr, jstring permissionStr) {
    if (isSELinuxDisabled) {
        return true;
    }

    ScopedUtfChars subjectContext(env, subjectContextStr);
    if (subjectContext.c_str() == NULL) {
        return false;
    }

    ScopedUtfChars objectContext(env, objectContextStr);
    if (objectContext.c_str() == NULL) {
        return false;
    }

    ScopedUtfChars objectClass(env, objectClassStr);
    if (objectClass.c_str() == NULL) {
        return false;
    }

    ScopedUtfChars permission(env, permissionStr);
    if (permission.c_str() == NULL) {
        return false;
    }

    char *tmp1 = const_cast<char *>(subjectContext.c_str());
    char *tmp2 = const_cast<char *>(objectContext.c_str());
    int accessGranted = selinux_check_access(tmp1, tmp2, objectClass.c_str(), permission.c_str(),
            NULL);

    ALOGV("checkSELinuxAccess(%s, %s, %s, %s) => %d", subjectContext.c_str(), objectContext.c_str(),
            objectClass.c_str(), permission.c_str(), accessGranted);

    return (accessGranted == 0) ? true : false;
}

/*
 * Function: native_restorecon
 * Purpose: restore default SELinux security context
 * Parameters: pathname: the pathname for the file to be relabeled
 * Returns: boolean: (true) file label successfully restored, (false) otherwise
 * Exceptions: none
 */
static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr, jint flags) {
    if (isSELinuxDisabled) {
        return true;
    }

    ScopedUtfChars pathname(env, pathnameStr);
    if (pathname.c_str() == NULL) {
        ALOGV("restorecon(%p) => threw exception", pathnameStr);
        return false;
    }

    int ret = selinux_android_restorecon(pathname.c_str(), flags);
    ALOGV("restorecon(%s) => %d", pathname.c_str(), ret);
    return (ret == 0);
}

/*
 * JNI registration.
 */
static const JNINativeMethod method_table[] = {
    /* name,                     signature,                    funcPtr */
    { "checkSELinuxAccess"       , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
    { "getContext"               , "()Ljava/lang/String;"                         , (void*)getCon           },
    { "getFileContext"           , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)getFileCon       },
    { "getPeerContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon       },
    { "getFileContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getFdCon         },
    { "getPidContext"            , "(I)Ljava/lang/String;"                        , (void*)getPidCon        },
    { "isSELinuxEnforced"        , "()Z"                                          , (void*)isSELinuxEnforced},
    { "isSELinuxEnabled"         , "()Z"                                          , (void*)isSELinuxEnabled },
    { "native_restorecon"        , "(Ljava/lang/String;I)Z"                       , (void*)native_restorecon},
    { "setFileContext"           , "(Ljava/lang/String;Ljava/lang/String;)Z"      , (void*)setFileCon       },
    { "setFSCreateContext"       , "(Ljava/lang/String;)Z"                        , (void*)setFSCreateCon   },
    { "fileSelabelLookup"        , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)fileSelabelLookup},
};

static int log_callback(int type, const char *fmt, ...) {
    va_list ap;
    int priority;

    switch (type) {
    case SELINUX_WARNING:
        priority = ANDROID_LOG_WARN;
        break;
    case SELINUX_INFO:
        priority = ANDROID_LOG_INFO;
        break;
    default:
        priority = ANDROID_LOG_ERROR;
        break;
    }
    va_start(ap, fmt);
    LOG_PRI_VA(priority, "SELinux", fmt, ap);
    va_end(ap);
    return 0;
}

int register_android_os_SELinux(JNIEnv *env) {
    union selinux_callback cb;
    cb.func_log = log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false;

    return RegisterMethodsOrDie(env, "android/os/SELinux", method_table, NELEM(method_table));
}

}
