decryption: Fetch file encryption from applied fstab [1/2]

Change-Id: I240177b8eee20bd06b7d558d6cba400359f76c6c
Signed-off-by: Mohd Faraz <androiabledroid@gmail.com>
diff --git a/Android.mk b/Android.mk
index 4e8186c..03de408 100755
--- a/Android.mk
+++ b/Android.mk
@@ -87,6 +87,7 @@
     system/core/fs_mgr/include/ \
     system/core/fs_mgr/libdm/include/ \
     system/core/fs_mgr/liblp/include/ \
+    system/core/fs_mgr/ \
     system/gsid/include/ \
     system/core/init/ \
     system/extras/ext4_utils/include \
@@ -349,6 +350,7 @@
         endif
         LOCAL_SHARED_LIBRARIES += libcryptfs_hw
     endif
+    TW_INCLUDE_LIBRESETPROP := true
 endif
 WITH_CRYPTO_UTILS := \
     $(if $(wildcard system/core/libcrypto_utils/android_pubkey.c),true)
@@ -508,6 +510,11 @@
     resetprop
 endif
 
+ifeq ($(TW_INCLUDE_LIBRESETPROP), true)
+TWRP_REQUIRED_MODULES += \
+    libresetprop
+endif
+
 TWRP_REQUIRED_MODULES += \
     hwservicemanager \
     hwservicemanager.rc \
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 8181c30..9a2a3aa 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -122,6 +122,8 @@
 extern bool datamedia;
 std::vector<users_struct> Users_List;
 
+std::string additional_fstab = "/etc/additional.fstab";
+
 TWPartitionManager::TWPartitionManager(void) {
 	mtp_was_enabled = false;
 	mtp_write_fd = -1;
@@ -157,12 +159,61 @@
 	return 0;
 }
 
+void inline Reset_Prop_From_Partition(std::string prop, std::string def, TWPartition *ven, TWPartition *odm) {
+	bool prop_on_odm = false, prop_on_vendor = false;
+	string prop_value;
+	if (odm) {
+		string odm_prop = TWFunc::Partition_Property_Get(prop, PartitionManager, "/odm", "etc/build.prop");
+		if (!odm_prop.empty()) {
+			prop_on_odm = true;
+			if (TWFunc::Property_Override(prop, odm_prop) == NOT_AVAILABLE) {
+				LOGERR("Unable to override '%s' due to missing libresetprop\n", prop.c_str());
+			} else {
+				prop_value = android::base::GetProperty(prop, "");
+				LOGINFO("Setting '%s' to '%s' from /odm/etc/build.prop\n", prop.c_str(), prop_value.c_str());
+			}
+		}
+	}
+	if (ven) {
+		string vendor_prop = TWFunc::Partition_Property_Get(prop, PartitionManager, "/vendor", "build.prop");
+		if (!vendor_prop.empty()) {
+			prop_on_vendor = true;
+			if (TWFunc::Property_Override(prop, vendor_prop) == NOT_AVAILABLE) {
+				LOGERR("Unable to override '%s' due to missing libresetprop\n", prop.c_str());
+			} else {
+				prop_value = android::base::GetProperty(prop, "");
+				LOGINFO("Setting '%s' to '%s' from /vendor/build.prop\n", prop.c_str(), prop_value.c_str());
+			}
+		}
+	}
+	if (!prop_on_odm && !prop_on_vendor && !def.empty()) {
+		if (TWFunc::Property_Override(prop, def) == NOT_AVAILABLE) {
+			LOGERR("Unable to override '%s' due to missing libresetprop\n", prop.c_str());
+		} else {
+			prop_value = android::base::GetProperty(prop, "");
+			LOGINFO("Setting '%s' to default value (%s)\n", prop.c_str(), prop_value.c_str());
+		}
+	}
+	prop_value = android::base::GetProperty(prop, "");
+	if (!prop_on_odm && !prop_on_vendor && !prop_value.empty() && def.empty()) {
+		if(TWFunc::Delete_Property(prop) == NOT_AVAILABLE) {
+			LOGERR("Unable to delete '%s' due to missing libresetprop\n", prop.c_str());
+		} else {
+			LOGINFO("Deleting property '%s'\n", prop.c_str());
+		}
+	}
+}
+
 int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, bool recovery_mode) {
 	FILE *fstabFile;
 	char fstab_line[MAX_FSTAB_LINE_LENGTH];
+	bool parse_userdata = false;
 	std::map<string, Flags_Map> twrp_flags;
 
 	fstabFile = fopen("/etc/twrp.flags", "rt");
+	if (Get_Super_Status()) {
+		Setup_Super_Devices();
+	}
 	if (fstabFile != NULL) {
 		LOGINFO("Reading /etc/twrp.flags\n");
 		while (fgets(fstab_line, sizeof(fstab_line), fstabFile) != NULL) {
@@ -218,9 +269,11 @@
 		}
 		fclose(fstabFile);
 	}
-
+	TWPartition *data = NULL;
+	TWPartition *meta = NULL;
+parse:
 	fstabFile = fopen(Fstab_Filename.c_str(), "rt");
-	if (fstabFile == NULL) {
+	if (!parse_userdata && fstabFile == NULL) {
 		LOGERR("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str());
 		return false;
 	} else
@@ -233,21 +286,41 @@
 		if (fstab_line[0] == '#')
 			continue;
 
+		if (parse_userdata) {
+			if (strstr(fstab_line, "/metadata") && !strstr(fstab_line, "/data")) {
+				Partitions.erase(std::find(Partitions.begin(), Partitions.end(), meta));
+				delete meta;
+			} else if (strstr(fstab_line, "/data")) {
+				Partitions.erase(std::find(Partitions.begin(), Partitions.end(), data));
+				delete data;
+			} else {
+				continue;
+			}
+		}
+
+
 		size_t line_size = strlen(fstab_line);
 		if (fstab_line[line_size - 1] != '\n')
 			fstab_line[line_size] = '\n';
 
 		TWPartition* partition = new TWPartition();
-		if (partition->Process_Fstab_Line(fstab_line, Display_Error, &twrp_flags))
+		if (partition->Process_Fstab_Line(fstab_line, Display_Error, parse_userdata ? NULL : &twrp_flags)) {
+			if (partition->Mount_Point == "/data") data = partition;
+			if (partition->Mount_Point == "/metadata") meta = partition;
+			if (partition->Is_Super && !Prepare_Super_Volume(partition)) {
+				goto clear;
+			}
 			Partitions.push_back(partition);
+		}
 		else
+clear:
 			delete partition;
 
 		memset(fstab_line, 0, sizeof(fstab_line));
 	}
 	fclose(fstabFile);
 
-	if (twrp_flags.size() > 0) {
+	if (!parse_userdata && twrp_flags.size() > 0) {
 		LOGINFO("Processing remaining twrp.flags\n");
 		// Add any items from twrp.flags that did not exist in the recovery.fstab
 		for (std::map<string, Flags_Map>::iterator mapit=twrp_flags.begin(); mapit!=twrp_flags.end(); mapit++) {
@@ -263,9 +336,35 @@
 			mapit->second.fstab_line = NULL;
 		}
 	}
-	if (Get_Super_Status()) {
-		Setup_Super_Devices();
+	TWPartition* ven = PartitionManager.Find_Partition_By_Path("/vendor");
+	TWPartition* odm = PartitionManager.Find_Partition_By_Path("/odm");
+	if (!parse_userdata) {
+
+		if (ven) ven->Mount(true);
+		if (odm) odm->Mount(true);
+		if (TWFunc::Find_Fstab(Fstab_Filename)) {
+			string service;
+			LOGINFO("Fstab: %s\n", Fstab_Filename.c_str());
+			TWFunc::copy_file(Fstab_Filename, additional_fstab, 0600, false);
+			Fstab_Filename = additional_fstab;
+			property_set("fstab.additional", "1");
+			TWFunc::Get_Service_From(ven, "keymaster", service);
+			LOGINFO("Keymaster version: '%s' \n", TWFunc::Get_Version_From_Service(service).c_str());
+			property_set("keymaster_ver", TWFunc::Get_Version_From_Service(service).c_str());
+			parse_userdata = true;
+			Reset_Prop_From_Partition("ro.crypto.dm_default_key.options_format.version", "", ven, odm);
+			Reset_Prop_From_Partition("ro.crypto.volume.metadata.method", "", ven, odm);
+			Reset_Prop_From_Partition("ro.crypto.volume.options", "", ven, odm);
+			Reset_Prop_From_Partition("external_storage.projid.enabled", "", ven, odm);
+			Reset_Prop_From_Partition("external_storage.casefold.enabled", "", ven, odm);
+			Reset_Prop_From_Partition("external_storage.sdcardfs.enabled", "", ven, odm);
+			goto parse;
+		} else {
+			LOGINFO("Unable to parse vendor fstab\n");
+		}
 	}
+	if (ven) ven->UnMount(true);
+	if (odm) odm->UnMount(true);
 	LOGINFO("Done processing fstab files\n");
 
 	if (recovery_mode) {
@@ -297,9 +396,6 @@
 				andsec_partition = (*iter);
 			else
 				(*iter)->Has_Android_Secure = false;
-
-			if ((*iter)->Is_Super && !Prepare_Super_Volume(*iter))
-				Partitions.erase(iter--);
 		}
 
 		Unlock_Block_Partitions();
@@ -430,7 +526,7 @@
 			Set_Crypto_Type("file");
 #ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
 #ifdef USE_FSCRYPT
-			if (android::vold::fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false, false, Decrypt_Data->Current_File_System)) {
+			if (android::vold::fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false, false, Decrypt_Data->Current_File_System, TWFunc::Path_Exists(additional_fstab) ? additional_fstab : "")) {
 				std::string crypto_blkdev = android::base::GetProperty("ro.crypto.fs_crypto_blkdev", "error");
 				Decrypt_Data->Decrypted_Block_Device = crypto_blkdev;
 				LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", crypto_blkdev.c_str());
diff --git a/partitions.hpp b/partitions.hpp
index 713337b..0a63d92 100755
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -36,6 +36,8 @@
 #define REPACK_ORIG_DIR "/tmp/repackorig/"
 #define REPACK_NEW_DIR "/tmp/repacknew/"
 
+#define NOT_AVAILABLE -2
+
 using namespace std;
 
 // BasePartition is used for overriding so we can run custom, device
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index c19494e..51d252a 100755
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -25,6 +25,7 @@
 #include <time.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <fstab/fstab.h>
 #include <sys/mount.h>
 #include <sys/reboot.h>
 #include <sys/sendfile.h>
@@ -47,6 +48,7 @@
 #include "abx-functions.hpp"
 #include "twcommon.h"
 #include "gui/gui.hpp"
+#include <fs_mgr_priv_boot_config.h>
 #ifndef BUILD_TWRPTAR_MAIN
 #include "data.hpp"
 #include "partitions.hpp"
@@ -1398,7 +1400,15 @@
 #ifdef TW_INCLUDE_LIBRESETPROP
     return setprop(Prop_Name.c_str(), Prop_Value.c_str(), false);
 #else
-    return -2;
+    return NOT_AVAILABLE;
+#endif
+}
+
+int TWFunc::Delete_Property(string Prop_Name) {
+#ifdef TW_INCLUDE_LIBRESETPROP
+    return delprop(Prop_Name.c_str(), false);
+#else
+    return NOT_AVAILABLE;
 #endif
 }
 
@@ -1557,4 +1567,81 @@
 	return res;
 }
 
+std::string GetFstabPath() {
+	for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
+		std::string suffix;
+
+		if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
+
+		for (const char* prefix : {// late-boot/post-boot locations
+			"/odm/etc/fstab.", "/vendor/etc/fstab.",
+			// early boot locations
+			"/system/etc/fstab.", "/first_stage_ramdisk/system/etc/fstab.",
+			"/fstab.", "/first_stage_ramdisk/fstab."}) {
+				std::string fstab_path = prefix + suffix;
+				LOGINFO("%s: %s\n", __func__, fstab_path.c_str());
+				if (access(fstab_path.c_str(), F_OK) == 0) return fstab_path;
+		}
+	}
+
+	return "";
+}
+
+bool TWFunc::Find_Fstab(string &fstab) {
+	fstab = GetFstabPath();
+	if (fstab == "") return false;
+	return true;
+}
+
+bool TWFunc::Get_Service_From(TWPartition *Partition, std::string Service, std::string &Res) {
+	Partition->Mount(true);
+	std::string Path = Partition->Get_Mount_Point() + "/etc/init/";
+	std::string Name;
+	std::vector<std::string> Data;
+	bool Found = false, ret = false;
+	DIR* dir;
+	struct dirent* der;
+	dir = opendir(Path.c_str());
+	while ((der = readdir(dir)) != NULL)
+	{
+		Name = der->d_name;
+		if (Name.find(Service) != string::npos) {
+			Found = true;
+			Path += Name;
+			break;
+		}
+	}
+	closedir(dir);
+
+	if (!Found) {
+		LOGINFO("Unable to locate service RC\n");
+		goto finish;
+	}
+
+	if (read_file(Path, Data) != 0) {
+		LOGINFO("Unable to read file '%s'\n", Path.c_str());
+		goto finish;
+	}
+
+	for (int index = 0; index < Data.size(); index++) {
+		Name = Data.at(index);
+		if (Name.find("service") != string::npos) {
+			Res = Name.substr(Name.find_last_of('/')+1);
+			ret = true;
+			goto finish;
+		}
+	}
+
+finish:
+	Partition->UnMount(true);
+	return ret;
+}
+
+std::string TWFunc::Get_Version_From_Service(std::string name) {
+	int start, end;
+	start = name.find('@') + 1;
+	end = name.find("-") - start;
+	return name.substr(start, end);
+}
+
 #endif // ndef BUILD_TWRPTAR_MAIN
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index 3fa2df6..02d51e1 100755
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -116,10 +116,14 @@
 	static bool Is_TWRP_App_In_System(); // Check if the TWRP app is installed in the system partition
 	static void checkforapp();
 	static int Property_Override(string Prop_Name, string Prop_Value); // Override properties (including ro. properties)
+	static int Delete_Property(string Prop_Name); // Delete properties (non-persistent properties only)
 	static void List_Mounts(); // List current mounts by the kernel
 	static void Clear_Bootloader_Message(); // Removes the bootloader message from misc for next boot
 	static string Check_For_TwrpFolder(); // Gets user defined path on storage where backups should be stored
 	static bool Check_Xml_Format(const std::string filename); // Return whether a xml is in plain xml or ABX format
+	static bool Find_Fstab(string &fstab);
+	static bool Get_Service_From(TWPartition *Partition, std::string Service, std::string &Ret);
+	static std::string Get_Version_From_Service(std::string name);
 
 	static bool abx_to_xml(const std::string path, std::string &result); // could we convert abx to xml (if so, return the full path to the converted file)
 private: