226 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * This file is part of MultiROM.
 | 
						|
 *
 | 
						|
 * MultiROM is free software: you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation, either version 3 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * MultiROM is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with MultiROM.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <dirent.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#include "../lib/log.h"
 | 
						|
#include "../lib/fstab.h"
 | 
						|
 | 
						|
#include "crypto/lollipop/cryptfs.h"
 | 
						|
 | 
						|
#define CMD_NONE 0
 | 
						|
#define CMD_DECRYPT 1
 | 
						|
#define CMD_REMOVE 2
 | 
						|
#define CMD_PWTYPE 3
 | 
						|
 | 
						|
static int get_footer_from_opts(char *output, size_t output_size, const char *opts2)
 | 
						|
{
 | 
						|
    char *r, *saveptr;
 | 
						|
    char *dup = strdup(opts2);
 | 
						|
    int res = -1;
 | 
						|
 | 
						|
    r = strtok_r(dup, ",", &saveptr);
 | 
						|
    while(r)
 | 
						|
    {
 | 
						|
        if(strncmp(r, "encryptable=", sizeof("encryptable=")-1) == 0)
 | 
						|
        {
 | 
						|
            snprintf(output, output_size, "%s", r + sizeof("encryptable=") - 1);
 | 
						|
            res = 0;
 | 
						|
            goto exit;
 | 
						|
        }
 | 
						|
 | 
						|
        r = strtok_r(NULL, ",", &saveptr);
 | 
						|
    }
 | 
						|
 | 
						|
exit:
 | 
						|
    free(dup);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
static void print_help(char *argv[]) {
 | 
						|
    printf("Usage: %s COMMAND ARGUMENTS\n"
 | 
						|
        "Available commands:\n"
 | 
						|
        "     decrypt PASSWORD - mount encrypted data partition to /realdata using PASSWORD\n"
 | 
						|
        "     remove - unmounts encrypted data\n"
 | 
						|
        "     pwtype - prints password type as integer\n",
 | 
						|
        argv[0]);
 | 
						|
}
 | 
						|
 | 
						|
static int handle_pwtype(int stdout_fd)
 | 
						|
{
 | 
						|
    if(cryptfs_check_footer() < 0)
 | 
						|
    {
 | 
						|
        ERROR("cryptfs_check_footer failed!");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    int pwtype = cryptfs_get_password_type();
 | 
						|
    if(pwtype < 0)
 | 
						|
    {
 | 
						|
        ERROR("cryptfs_get_password_type failed!");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    char buff[32];
 | 
						|
    snprintf(buff, sizeof(buff), "%d\n", pwtype);
 | 
						|
    write(stdout_fd, buff, strlen(buff));
 | 
						|
    fsync(stdout_fd);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int handle_decrypt(int stdout_fd, char *password)
 | 
						|
{
 | 
						|
    DIR *d;
 | 
						|
    struct dirent *de;
 | 
						|
    char buff[256];
 | 
						|
    int res = -1;
 | 
						|
 | 
						|
    if(cryptfs_check_footer() < 0)
 | 
						|
    {
 | 
						|
        ERROR("cryptfs_check_footer failed!");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    if(cryptfs_check_passwd(password) < 0)
 | 
						|
    {
 | 
						|
        ERROR("cryptfs_check_passwd failed!");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    d = opendir("/dev/block/");
 | 
						|
    if(!d)
 | 
						|
    {
 | 
						|
        ERROR("Failed to open /dev/block, wth? %s", strerror(errno));
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    // find the block device
 | 
						|
    while((de = readdir(d)))
 | 
						|
    {
 | 
						|
        if(de->d_type == DT_BLK && strncmp(de->d_name, "dm-", 3) == 0)
 | 
						|
        {
 | 
						|
            snprintf(buff, sizeof(buff), "/dev/block/%s\n", de->d_name);
 | 
						|
            write(stdout_fd, buff, strlen(buff));
 | 
						|
            fsync(stdout_fd);
 | 
						|
            res = 0;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    closedir(d);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
static int handle_remove(void)
 | 
						|
{
 | 
						|
    if(delete_crypto_blk_dev("userdata") < 0)
 | 
						|
    {
 | 
						|
        ERROR("delete_crypto_blk_dev failed!");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char *argv[])
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int res = 1;
 | 
						|
    int cmd = CMD_NONE;
 | 
						|
    int stdout_fd;
 | 
						|
    char footer_location[256];
 | 
						|
    struct fstab *fstab;
 | 
						|
    struct fstab_part *p;
 | 
						|
    char *argument = NULL;
 | 
						|
 | 
						|
    for(i = 1; i < argc; ++i)
 | 
						|
    {
 | 
						|
        if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
 | 
						|
        {
 | 
						|
            print_help(argv);
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        else if(cmd == CMD_NONE)
 | 
						|
        {
 | 
						|
            if(strcmp(argv[i], "decrypt") == 0)
 | 
						|
                cmd = CMD_DECRYPT;
 | 
						|
            else if(strcmp(argv[i], "remove") == 0)
 | 
						|
                cmd = CMD_REMOVE;
 | 
						|
            else if(strcmp(argv[i], "pwtype") == 0)
 | 
						|
                cmd = CMD_PWTYPE;
 | 
						|
        }
 | 
						|
        else if(!argument)
 | 
						|
        {
 | 
						|
            argument = argv[i];
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if(argc == 1 || cmd == CMD_NONE || (cmd == CMD_DECRYPT && !argument))
 | 
						|
    {
 | 
						|
        print_help(argv);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    fstab = fstab_auto_load();
 | 
						|
    if(!fstab)
 | 
						|
    {
 | 
						|
        ERROR("Failed to load fstab!");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    p = fstab_find_first_by_path(fstab, "/data");
 | 
						|
    if(!p)
 | 
						|
    {
 | 
						|
        ERROR("Failed to find /data partition in fstab\n");
 | 
						|
        goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    if(get_footer_from_opts(footer_location, sizeof(footer_location), p->options2) < 0)
 | 
						|
        goto exit;
 | 
						|
 | 
						|
    INFO("Setting encrypted partition data to %s %s %s\n", p->device, footer_location, p->type);
 | 
						|
    set_partition_data(p->device, footer_location, p->type);
 | 
						|
 | 
						|
    // cryptfs prints informations, we don't want that
 | 
						|
    stdout_fd = dup(1);
 | 
						|
    freopen("/dev/null", "a", stdout);
 | 
						|
 | 
						|
    switch(cmd)
 | 
						|
    {
 | 
						|
        case CMD_PWTYPE:
 | 
						|
            if(handle_pwtype(stdout_fd) < 0)
 | 
						|
                goto exit;
 | 
						|
            break;
 | 
						|
        case CMD_DECRYPT:
 | 
						|
            if(handle_decrypt(stdout_fd, argument) < 0)
 | 
						|
                goto exit;
 | 
						|
            break;
 | 
						|
        case CMD_REMOVE:
 | 
						|
            if(handle_remove() < 0)
 | 
						|
                goto exit;
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    res = 0;
 | 
						|
exit:
 | 
						|
    fstab_destroy(fstab);
 | 
						|
    return res;
 | 
						|
}
 |