summaryrefslogtreecommitdiff
path: root/common/src/intercept_policy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/intercept_policy.cpp')
-rw-r--r--common/src/intercept_policy.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/common/src/intercept_policy.cpp b/common/src/intercept_policy.cpp
new file mode 100644
index 0000000..1fbaafd
--- /dev/null
+++ b/common/src/intercept_policy.cpp
@@ -0,0 +1,271 @@
+#include <tfe_utils.h>
+#include <MESA/maat.h>
+#include <cjson/cJSON.h>
+#include <tfe_resource.h>
+#include <intercept_policy.h>
+
+struct intercept_param
+{
+ uint64_t rule_id;
+ int ref_cnt;
+ int keyring_for_trusted;
+ int keyring_for_untrusted;
+ int decryption_profile;
+ int tcp_option_profile;
+};
+
+struct intercept_policy_enforcer
+{
+ struct maat *maat;
+ int table_id;
+ void *logger;
+};
+
+static void intercept_param_new_cb(const char *table_name, int table_id, const char *key, const char *table_line, void **ad, long argl, void *argp)
+{
+ size_t len = 0;
+ size_t offset = 0;
+ char *json_str = NULL;
+ cJSON *json = NULL;
+ cJSON *item = NULL;
+ struct intercept_param *param = NULL;
+ struct intercept_policy_enforcer *enforcer = (struct intercept_policy_enforcer *)argp;
+
+ if (maat_helper_read_column(table_line, 7, &offset, &len) < 0)
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept user region: %s", table_line);
+ goto error_out;
+ }
+
+ json_str = ALLOC(char, len + 1);
+ memcpy(json_str, table_line + offset, len);
+ json = cJSON_Parse(json_str);
+ if (json == NULL)
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: id = %s", key);
+ goto error_out;
+ }
+
+ item = cJSON_GetObjectItem(json, "protocol");
+ if (unlikely(!item || !cJSON_IsString(item)))
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: %s invalid protocol format", key);
+ goto error_out;
+ }
+ if (0 != strcasecmp(item->valuestring, "SSL") && 0 != strcasecmp(item->valuestring, "HTTP"))
+ {
+ goto error_out;
+ }
+
+ param = ALLOC(struct intercept_param, 1);
+ param->rule_id = atoll(key);
+ param->ref_cnt = 1;
+ param->keyring_for_trusted = 1;
+ param->keyring_for_untrusted = 0;
+ param->decryption_profile = 0;
+ param->tcp_option_profile = 0;
+
+ item = cJSON_GetObjectItem(json, "keyring_for_trusted");
+ if (item)
+ {
+ if (item->type == cJSON_Number)
+ {
+ param->keyring_for_trusted = item->valueint;
+ }
+ else if (item->type == cJSON_String)
+ {
+ param->keyring_for_trusted = atoi(item->valuestring);
+ }
+ else
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: %lu invalid keyring_for_trusted format", param->rule_id);
+ }
+ }
+
+ item = cJSON_GetObjectItem(json, "keyring_for_untrusted");
+ if (item)
+ {
+ if (item->type == cJSON_Number)
+ {
+ param->keyring_for_untrusted = item->valueint;
+ }
+ else if (item->type == cJSON_String)
+ {
+ param->keyring_for_untrusted = atoi(item->valuestring);
+ }
+ else
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: %lu invalid keyring_for_untrusted format", param->rule_id);
+ }
+ }
+
+ item = cJSON_GetObjectItem(json, "decryption");
+ if (item)
+ {
+ if (item->type == cJSON_Number)
+ {
+ param->decryption_profile = item->valueint;
+ }
+ else if (item->type == cJSON_String)
+ {
+ param->decryption_profile = atoi(item->valuestring);
+ }
+ else
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: %lu invalid decryption_profile format", param->rule_id);
+ }
+ }
+
+ item = cJSON_GetObjectItem(json, "tcp_option_profile");
+ if (item)
+ {
+ if (item->type == cJSON_Number)
+ {
+ param->tcp_option_profile = item->valueint;
+ }
+ else if (item->type == cJSON_String)
+ {
+ param->tcp_option_profile = atoi(item->valuestring);
+ }
+ else
+ {
+ TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: %lu invalid tcp_option_profile format", param->rule_id);
+ }
+ }
+
+ *ad = param;
+ TFE_LOG_INFO(enforcer->logger, "Add intercept policy: %lu", param->rule_id);
+
+error_out:
+ if (json)
+ {
+ cJSON_Delete(json);
+ }
+ if (json_str)
+ {
+ free(json_str);
+ }
+}
+
+static void intercept_param_free_cb(int table_id, void **ad, long argl, void *argp)
+{
+ struct intercept_policy_enforcer *enforcer = (struct intercept_policy_enforcer *)argp;
+ struct intercept_param *param = (struct intercept_param *)*ad;
+ if (param == NULL)
+ {
+ return;
+ }
+
+ if ((__sync_sub_and_fetch(&param->ref_cnt, 1) == 0))
+ {
+ TFE_LOG_INFO(enforcer->logger, "Del intercept policy %lu", param->rule_id);
+ free(param);
+ *ad = NULL;
+ }
+}
+
+static void intercept_param_dup_cb(int table_id, void **to, void **from, long argl, void *argp)
+{
+ struct intercept_param *param = (struct intercept_param *)*from;
+ if (param)
+ {
+ __sync_add_and_fetch(&(param->ref_cnt), 1);
+ *to = param;
+ }
+ else
+ {
+ *to = NULL;
+ }
+}
+
+static void intercept_param_free(struct intercept_param *param)
+{
+ intercept_param_free_cb(0, (void **)&param, 0, NULL);
+}
+
+struct intercept_policy_enforcer *intercept_policy_enforcer_create(void *logger)
+{
+ int ret = 0;
+ struct intercept_policy_enforcer *enforcer = ALLOC(struct intercept_policy_enforcer, 1);
+ enforcer->maat = (struct maat *)tfe_bussiness_resouce_get(STATIC_MAAT);
+ enforcer->logger = logger;
+ enforcer->table_id = maat_get_table_id(enforcer->maat, "TSG_SECURITY_COMPILE");
+
+ if (enforcer->table_id < 0)
+ {
+ TFE_LOG_ERROR(enforcer->logger, "failed at register table of TSG_SECURITY_COMPILE, ret = %d", enforcer->table_id);
+ goto error_out;
+ }
+
+ ret = maat_plugin_table_ex_schema_register(enforcer->maat,
+ "TSG_SECURITY_COMPILE",
+ intercept_param_new_cb,
+ intercept_param_free_cb,
+ intercept_param_dup_cb,
+ 0,
+ enforcer);
+ if (ret != 0)
+ {
+ TFE_LOG_ERROR(enforcer->logger, "failed at register callback of TSG_SECURITY_COMPILE, ret = %d", ret);
+ goto error_out;
+ }
+
+ return enforcer;
+
+error_out:
+ intercept_policy_enforce_destory(enforcer);
+ return NULL;
+}
+
+void intercept_policy_enforce_destory(struct intercept_policy_enforcer *enforcer)
+{
+ if (enforcer)
+ {
+ free(enforcer);
+ enforcer = NULL;
+ }
+}
+
+// return 0 : success
+// return -1 : error (need passthrough)
+int intercept_policy_enforce(struct intercept_policy_enforcer *enforcer, struct tfe_cmsg *cmsg)
+{
+ int ret = 0;
+ uint16_t size = 0;
+ uint64_t rule_id = 0;
+ char buff[16] = {0};
+ struct intercept_param *param = NULL;
+
+ int passthrough = 1;
+ char reason[] = "Invalid Intercept Param";
+
+ ret = tfe_cmsg_get_value(cmsg, TFE_CMSG_POLICY_ID, (unsigned char *)&rule_id, sizeof(rule_id), &size);
+ if (ret < 0)
+ {
+ TFE_LOG_ERROR(g_default_logger, "Failed at fetch intercept rule_id from cmsg: %s", strerror(-ret));
+ goto error_passthrough;
+ }
+
+ snprintf(buff, sizeof(buff), "%lu", rule_id);
+ param = (struct intercept_param *)maat_plugin_table_get_ex_data(enforcer->maat, enforcer->table_id, buff);
+ if (param == NULL)
+ {
+ TFE_LOG_INFO(enforcer->logger, "Failed to get intercept parameter of policy %lu.", rule_id);
+ goto error_passthrough;
+ }
+
+ tfe_cmsg_set(cmsg, TFE_CMSG_TCP_OPTION_PROFILE_ID, (const unsigned char *)&(param->tcp_option_profile), sizeof(param->tcp_option_profile));
+ tfe_cmsg_set(cmsg, TFE_CMSG_DECRYPTION_PROFILE_ID, (const unsigned char *)&(param->decryption_profile), sizeof(param->decryption_profile));
+ tfe_cmsg_set(cmsg, TFE_CMSG_KEYRING_FOR_TRUSTED_ID, (const unsigned char *)&(param->keyring_for_trusted), sizeof(param->keyring_for_trusted));
+ tfe_cmsg_set(cmsg, TFE_CMSG_KEYRING_FOR_UNTRUSTED, (const unsigned char *)&(param->keyring_for_untrusted), sizeof(param->keyring_for_untrusted));
+
+ intercept_param_free(param);
+
+ return 0;
+
+error_passthrough:
+ tfe_cmsg_set(cmsg, TFE_CMSG_TCP_PASSTHROUGH, (const unsigned char *)&passthrough, sizeof(passthrough));
+ tfe_cmsg_set(cmsg, TFE_CMSG_SSL_PASSTHROUGH_REASON, (const unsigned char *)&reason, strlen(reason));
+
+ return -1;
+} \ No newline at end of file