Files
Sven Geuer d3a714dbb6 Fix a few typos on the manpages and source code.
These typos has been identified in Debian and are currently patched
there.
2025-02-18 22:55:08 +01:00

831 lines
21 KiB
C

/* -*- coding: utf-8 -*- */
/* -*- mode: c -*- */
/*
* Dislocker -- enables to read/write on BitLocker encrypted partitions under
* Linux
* Copyright (C) 2012-2013 Romain Coltel, Hervé Schauer Consultants
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <string.h>
#include <getopt.h>
#include "dislocker/common.h"
#include "dislocker/config.priv.h"
#include "dislocker/dislocker.priv.h"
/**
* Hide a commandline option, replacing the actual optarg by 'X's.
*
* @param opt The option to hide
*/
static void hide_opt(char* opt)
{
if(!opt)
return;
size_t len = strlen(opt);
while(len)
{
opt[--len] = 'X';
}
}
/* These functions are wrappers around the appropriate dis_setopt call */
static void setclearkey(dis_context_t dis_ctx, char* optarg)
{
(void) optarg;
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_CLEAR_KEY, &trueval);
}
static void setbekfile(dis_context_t dis_ctx, char* optarg)
{
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_BEK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_BEK_FILE_PATH, optarg);
}
static void setforceblock(dis_context_t dis_ctx, char* optarg)
{
off_t force;
if(optarg)
force = (unsigned char) strtol(optarg, NULL, 10);
else
force = 1;
dis_setopt(dis_ctx, DIS_OPT_FORCE_BLOCK, &force);
}
static void setfvek(dis_context_t dis_ctx, char* optarg)
{
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_FVEK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_FVEK_FILE_PATH, optarg);
}
static void setvmk(dis_context_t dis_ctx, char* optarg)
{
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_VMK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_VMK_FILE_PATH, optarg);
}
static void setlogfile(dis_context_t dis_ctx, char* optarg)
{
dis_setopt(dis_ctx, DIS_OPT_LOG_FILE_PATH, optarg);
}
static void setoffset(dis_context_t dis_ctx, char* optarg)
{
off_t offset = (off_t) strtoll(optarg, NULL, 10);
dis_setopt(dis_ctx, DIS_OPT_VOLUME_OFFSET, &offset);
}
static void setrecoverypwd(dis_context_t dis_ctx, char* optarg)
{
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_RECOVERY_PASSWORD, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_RECOVERY_PASSWORD, optarg);
hide_opt(optarg);
}
static void setquiet(dis_context_t dis_ctx, char* optarg)
{
(void) optarg;
DIS_LOGS l = L_QUIET;
dis_setopt(dis_ctx, DIS_OPT_VERBOSITY, &l);
}
static void setro(dis_context_t dis_ctx, char* optarg)
{
(void) optarg;
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_READ_ONLY, &trueval);
}
static void setstateok(dis_context_t dis_ctx, char* optarg)
{
(void) optarg;
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_DONT_CHECK_VOLUME_STATE, &trueval);
}
static void setuserpassword(dis_context_t dis_ctx, char* optarg)
{
int trueval = TRUE;
dis_setopt(dis_ctx, DIS_OPT_USE_USER_PASSWORD, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_USER_PASSWORD, optarg);
hide_opt(optarg);
}
static void setverbosity(dis_context_t dis_ctx, char* optarg)
{
dis_ctx->cfg.verbosity = (DIS_LOGS)strtol(optarg, NULL, 10);
}
/* Structure used to define dislocker's options */
struct _dis_options {
struct option opt;
void (*fn)(dis_context_t dis_ctx, char* optarg);
};
static struct _dis_options dis_opt[] = {
{ {"clearkey", no_argument, NULL, 'c'}, setclearkey },
{ {"bekfile", required_argument, NULL, 'f'}, setbekfile },
{ {"force-block", optional_argument, NULL, 'F'}, setforceblock },
{ {"help", no_argument, NULL, 'h'}, NULL },
{ {"fvek", required_argument, NULL, 'k'}, setfvek },
{ {"vmk", required_argument, NULL, 'K'}, setvmk },
{ {"logfile", required_argument, NULL, 'l'}, setlogfile },
{ {"offset", required_argument, NULL, 'O'}, setoffset },
{ {"options", required_argument, NULL, 'o'}, NULL },
{ {"recovery-password", optional_argument, NULL, 'p'}, setrecoverypwd },
{ {"quiet", no_argument, NULL, 'q'}, setquiet },
{ {"readonly", no_argument, NULL, 'r'}, setro },
{ {"ro", no_argument, NULL, 'r'}, setro },
{ {"stateok", no_argument, NULL, 's'}, setstateok },
{ {"user-password", optional_argument, NULL, 'u'}, setuserpassword },
{ {"verbosity", no_argument, NULL, 'v'}, setverbosity },
{ {"volume", required_argument, NULL, 'V'}, NULL }
};
/**
* Print program's usage
*/
void dis_usage()
{
fprintf(stderr,
PROGNAME " by " AUTHOR ", v" VERSION " (compiled for " __OS "/" __ARCH ")\n"
#ifdef VERSION_DBG
"Compiled version: " VERSION_DBG "\n"
#endif
"\n"
"Usage: " PROGNAME " [-hqrsv] [-l LOG_FILE] [-O OFFSET] [-V VOLUME DECRYPTMETHOD -F[N]] [-- ARGS...]\n"
" with DECRYPTMETHOD = -p[RECOVERY_PASSWORD]|-f BEK_FILE|-u[USER_PASSWORD]|-k FVEK_FILE|-K VMK_FILE|-c\n"
"\n"
"Options:\n"
" -c, --clearkey decrypt volume using a clear key (default)\n"
" -f, --bekfile BEKFILE\n"
" decrypt volume using the bek file (on USB key)\n"
" -F, --force-block=[N] force use of metadata block number N (1, 2 or 3)\n"
" -h, --help print this help and exit\n"
" -k, --fvek FVEK_FILE decrypt volume using the FVEK directly\n"
" -K, --vmk VMK_FILE decrypt volume using the VMK directly\n"
" -l, --logfile LOG_FILE\n"
" put messages into this file (stdout by default)\n"
" -O, --offset OFFSET BitLocker partition offset, in bytes (default is 0)\n"
" -p, --recovery-password=[RECOVERY_PASSWORD]\n"
" decrypt volume using the recovery password method\n"
" -q, --quiet do NOT display anything\n"
" -r, --readonly do not allow one to write on the BitLocker volume\n"
" -s, --stateok do not check the volume's state, assume it's ok to mount it\n"
" -u, --user-password=[USER_PASSWORD]\n"
" decrypt volume using the user password method\n"
" -v, --verbosity increase verbosity (CRITICAL errors are displayed by default)\n"
" -V, --volume VOLUME volume to get metadata and keys from\n"
"\n"
" -- end of program options, beginning of FUSE's ones\n"
"\n"
" ARGS are any arguments you want to pass to FUSE. You need to pass at least\n"
"the mount-point.\n"
"\n"
);
}
/**
* Parse the --options parameter's value
*
* @param dis_ctx Dislocker's context
* @param optstr The value passed with the --options parameter
*/
static void parse_options(dis_context_t dis_ctx, char* optstr)
{
char* tok = NULL;
size_t nb_options = sizeof(dis_opt)/sizeof(struct _dis_options);
size_t i;
size_t opt_len;
tok = strtok(optstr, ",");
while(tok != NULL)
{
for(i = 0; i < nb_options; i++)
{
opt_len = strlen(dis_opt[i].opt.name);
if(strncmp(dis_opt[i].opt.name, tok, opt_len) == 0)
{
if(tok[opt_len] == '=' && tok[opt_len] != '\0')
dis_opt[i].fn(dis_ctx, &tok[opt_len + 1]);
else
dis_opt[i].fn(dis_ctx, NULL);
}
}
tok = strtok(NULL, ",");
}
}
/**
* Parse arguments strings
*
* @warning If -h/--help is encountered, the help is printed and the program
* exits (using exit(EXIT_SUCCESS)).
*
* @param dis_ctx Dislocker's context
* @param argc Number of arguments given to the program
* @param argv Arguments given to the program
* @return Return the number of arguments which are still waiting to be studied.
* If -1 is returned, then an error occurred and the configuration isn't set.
*/
int dis_getopts(dis_context_t dis_ctx, int argc, char** argv)
{
/** See man getopt_long(3) */
extern int optind;
int optchar = 0;
size_t nb_options = sizeof(dis_opt)/sizeof(struct _dis_options);
/* Options which could be passed as argument */
const char short_opts[] = "cf:F::hk:K:l:O:o:p::qrsu::vV:";
struct option* long_opts;
if(!dis_ctx || !argv)
return -1;
dis_config_t* cfg = &dis_ctx->cfg;
int trueval = TRUE;
long_opts = malloc(nb_options * sizeof(struct option));
while(nb_options--)
{
long_opts[nb_options].name = dis_opt[nb_options].opt.name;
long_opts[nb_options].has_arg = dis_opt[nb_options].opt.has_arg;
long_opts[nb_options].flag = dis_opt[nb_options].opt.flag;
long_opts[nb_options].val = dis_opt[nb_options].opt.val;
}
while((optchar = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1)
{
switch(optchar)
{
case 'c':
{
dis_setopt(dis_ctx, DIS_OPT_USE_CLEAR_KEY, &trueval);
break;
}
case 'f':
{
dis_setopt(dis_ctx, DIS_OPT_USE_BEK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_BEK_FILE_PATH, optarg);
break;
}
case 'F':
{
off_t force;
if(optarg)
force = (unsigned char) strtol(optarg, NULL, 10);
else
force = 1;
dis_setopt(dis_ctx, DIS_OPT_FORCE_BLOCK, &force);
break;
}
case 'h':
{
dis_usage();
dis_free_args(dis_ctx);
exit(EXIT_SUCCESS);
}
case 'k':
{
dis_setopt(dis_ctx, DIS_OPT_USE_FVEK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_FVEK_FILE_PATH, optarg);
break;
}
case 'K':
{
dis_setopt(dis_ctx, DIS_OPT_USE_VMK_FILE, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_VMK_FILE_PATH, optarg);
break;
}
case 'l':
{
dis_setopt(dis_ctx, DIS_OPT_LOG_FILE_PATH, optarg);
break;
}
case 'O':
{
off_t offset = (off_t) strtoll(optarg, NULL, 10);
dis_setopt(dis_ctx, DIS_OPT_VOLUME_OFFSET, &offset);
break;
}
case 'o':
{
parse_options(dis_ctx, optarg);
break;
}
case 'p':
{
dis_setopt(dis_ctx, DIS_OPT_USE_RECOVERY_PASSWORD, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_RECOVERY_PASSWORD, optarg);
hide_opt(optarg);
break;
}
case 'q':
{
DIS_LOGS l = L_QUIET;
dis_setopt(dis_ctx, DIS_OPT_VERBOSITY, &l);
break;
}
case 'r':
{
dis_setopt(dis_ctx, DIS_OPT_READ_ONLY, &trueval);
break;
}
case 's':
{
dis_setopt(dis_ctx, DIS_OPT_DONT_CHECK_VOLUME_STATE, &trueval);
break;
}
case 'u':
{
dis_setopt(dis_ctx, DIS_OPT_USE_USER_PASSWORD, &trueval);
dis_setopt(dis_ctx, DIS_OPT_SET_USER_PASSWORD, optarg);
hide_opt(optarg);
break;
}
case 'v':
{
if(cfg->verbosity != L_QUIET)
cfg->verbosity++;
break;
}
case 'V':
{
dis_setopt(dis_ctx, DIS_OPT_VOLUME_PATH, optarg);
break;
}
case '?':
default:
{
dis_usage();
free(long_opts);
dis_free_args(dis_ctx);
return -1;
}
}
}
/* Check verbosity */
if(cfg->verbosity > L_DEBUG)
cfg->verbosity = L_DEBUG;
if(cfg->verbosity < L_CRITICAL)
cfg->verbosity = L_CRITICAL;
/* Check decryption method */
if(!cfg->decryption_mean)
cfg->decryption_mean |= DIS_USE_CLEAR_KEY;
/* Check if a block is forced */
if(cfg->force_block != 1 &&
cfg->force_block != 2 &&
cfg->force_block != 3)
cfg->force_block = 0;
free(long_opts);
return optind;
}
/**
* Get dislocker's option
*
* @param dis_ctx Dislocker's context
* @param opt_name The option's name to get
* @param opt_value The retrieved value of the option. This is stored in
*opt_value.
*/
int dis_getopt(dis_context_t dis_ctx, dis_opt_e opt_name, void** opt_value)
{
if (!dis_ctx || !opt_value)
return FALSE;
dis_config_t* cfg = &dis_ctx->cfg;
switch(opt_name)
{
case DIS_OPT_VOLUME_PATH:
*opt_value = cfg->volume_path;
break;
case DIS_OPT_USE_CLEAR_KEY:
if(cfg->decryption_mean & DIS_USE_CLEAR_KEY)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_USE_BEK_FILE:
if(cfg->decryption_mean & DIS_USE_BEKFILE)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_SET_BEK_FILE_PATH:
*opt_value = cfg->bek_file;
break;
case DIS_OPT_USE_RECOVERY_PASSWORD:
if(cfg->decryption_mean & DIS_USE_RECOVERY_PASSWORD)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_SET_RECOVERY_PASSWORD:
*opt_value = cfg->recovery_password;
break;
case DIS_OPT_USE_USER_PASSWORD:
if(cfg->decryption_mean & DIS_USE_USER_PASSWORD)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_SET_USER_PASSWORD:
*opt_value = cfg->user_password;
break;
case DIS_OPT_USE_FVEK_FILE:
if(cfg->decryption_mean & DIS_USE_FVEKFILE)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_SET_FVEK_FILE_PATH:
*opt_value = cfg->fvek_file;
break;
case DIS_OPT_USE_VMK_FILE:
if(cfg->decryption_mean & DIS_USE_VMKFILE)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_SET_VMK_FILE_PATH:
*opt_value = cfg->vmk_file;
break;
case DIS_OPT_VERBOSITY:
*opt_value = (void*) cfg->verbosity;
break;
case DIS_OPT_LOG_FILE_PATH:
*opt_value = cfg->log_file;
break;
case DIS_OPT_FORCE_BLOCK:
*opt_value = (void*) ((long) cfg->force_block);
break;
case DIS_OPT_VOLUME_OFFSET:
*opt_value = (void*) cfg->offset;
break;
case DIS_OPT_READ_ONLY:
if(cfg->flags & DIS_FLAG_READ_ONLY)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_DONT_CHECK_VOLUME_STATE:
if(cfg->flags & DIS_FLAG_DONT_CHECK_VOLUME_STATE)
*opt_value = (void*) TRUE;
else
*opt_value = (void*) FALSE;
break;
case DIS_OPT_INITIALIZE_STATE:
*opt_value = (void*) cfg->init_stop_at;
break;
}
return TRUE;
}
static void set_decryption_mean(dis_config_t* cfg, int set, unsigned value)
{
if(set == TRUE)
cfg->decryption_mean |= value;
else
cfg->decryption_mean &= (unsigned) ~value;
}
/**
* Modify dislocker's options one-by-one
*
* @param dis_ctx Dislocker's context
* @param opt_name The option's name to change
* @param opt_value The new value of the option. Note that this is a pointer. If
* NULL, the default value -which is not necessarily usable- will be set.
*/
int dis_setopt(dis_context_t dis_ctx, dis_opt_e opt_name, const void* opt_value)
{
if (!dis_ctx)
return FALSE;
dis_config_t* cfg = &dis_ctx->cfg;
switch(opt_name)
{
case DIS_OPT_VOLUME_PATH:
if(cfg->volume_path != NULL)
free(cfg->volume_path);
if(opt_value == NULL)
cfg->volume_path = NULL;
else
cfg->volume_path = strdup((const char*) opt_value);
break;
case DIS_OPT_USE_CLEAR_KEY:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_CLEAR_KEY;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_CLEAR_KEY);
break;
case DIS_OPT_USE_BEK_FILE:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_BEKFILE;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_BEKFILE);
break;
case DIS_OPT_SET_BEK_FILE_PATH:
if(cfg->bek_file != NULL)
free(cfg->bek_file);
if(opt_value == NULL)
cfg->bek_file = NULL;
else
cfg->bek_file = strdup((const char*) opt_value);
break;
case DIS_OPT_USE_RECOVERY_PASSWORD:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_RECOVERY_PASSWORD;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_RECOVERY_PASSWORD);
break;
case DIS_OPT_SET_RECOVERY_PASSWORD:
if(cfg->recovery_password != NULL)
free(cfg->recovery_password);
if(opt_value == NULL)
cfg->recovery_password = NULL;
else
{
const char* v = (const char*) opt_value;
cfg->recovery_password = (uint8_t *) strdup(v);
}
break;
case DIS_OPT_USE_USER_PASSWORD:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_USER_PASSWORD;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_USER_PASSWORD);
break;
case DIS_OPT_SET_USER_PASSWORD:
if(cfg->user_password != NULL)
free(cfg->user_password);
if(opt_value == NULL)
cfg->user_password = NULL;
else
{
const char* v = (const char*) opt_value;
cfg->user_password = (uint8_t *) strdup(v);
}
break;
case DIS_OPT_USE_FVEK_FILE:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_FVEKFILE;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_FVEKFILE);
break;
case DIS_OPT_SET_FVEK_FILE_PATH:
if(cfg->fvek_file != NULL)
free(cfg->fvek_file);
if(opt_value == NULL)
cfg->fvek_file = NULL;
else
cfg->fvek_file = strdup((const char*) opt_value);
break;
case DIS_OPT_USE_VMK_FILE:
if(opt_value == NULL)
cfg->decryption_mean &= (unsigned) ~DIS_USE_VMKFILE;
else
set_decryption_mean(cfg, *(int*) opt_value, DIS_USE_VMKFILE);
break;
case DIS_OPT_SET_VMK_FILE_PATH:
if(cfg->vmk_file != NULL)
free(cfg->vmk_file);
if(opt_value == NULL)
cfg->vmk_file = NULL;
else
cfg->vmk_file = strdup((const char*) opt_value);
break;
case DIS_OPT_VERBOSITY:
if(opt_value == NULL)
cfg->verbosity = 0;
else
{
DIS_LOGS l = *(DIS_LOGS*) opt_value;
if(l >= L_QUIET && l <= L_DEBUG)
cfg->verbosity = l;
else
cfg->verbosity = 0;
}
break;
case DIS_OPT_LOG_FILE_PATH:
if(cfg->log_file != NULL)
free(cfg->log_file);
if(opt_value == NULL)
cfg->log_file = NULL;
else
cfg->log_file = strdup((const char*) opt_value);
break;
case DIS_OPT_FORCE_BLOCK:
if(opt_value == NULL)
cfg->force_block = 0;
else
{
int uc = *(int*) opt_value;
if(uc >= 1 && uc <= 3)
cfg->force_block = (unsigned char) uc;
else
cfg->force_block = 0;
}
break;
case DIS_OPT_VOLUME_OFFSET:
if(opt_value == NULL)
cfg->offset = 0;
else
cfg->offset = *(off_t*) opt_value;
break;
case DIS_OPT_READ_ONLY:
if(opt_value == NULL)
cfg->flags &= (unsigned) ~DIS_FLAG_READ_ONLY;
else
{
int flag = *(int*) opt_value;
if(flag == TRUE)
cfg->flags |= DIS_FLAG_READ_ONLY;
else
cfg->flags &= (unsigned) ~DIS_FLAG_READ_ONLY;
}
break;
case DIS_OPT_DONT_CHECK_VOLUME_STATE:
if(opt_value == NULL)
cfg->flags &= (unsigned) ~DIS_FLAG_DONT_CHECK_VOLUME_STATE;
else
{
int flag = *(int*) opt_value;
if(flag == TRUE)
cfg->flags |= DIS_FLAG_DONT_CHECK_VOLUME_STATE;
else
cfg->flags &= (unsigned) ~DIS_FLAG_DONT_CHECK_VOLUME_STATE;
}
break;
case DIS_OPT_INITIALIZE_STATE:
if(opt_value == NULL)
cfg->init_stop_at = DIS_STATE_COMPLETE_EVERYTHING;
else
{
dis_state_e state = *(dis_state_e*) opt_value;
cfg->init_stop_at = state;
}
break;
}
return TRUE;
}
/**
* Free dis_config_t members
*
* @param cfg Dislocker's config
*/
void dis_free_args(dis_context_t dis_ctx)
{
if (!dis_ctx)
return;
dis_config_t* cfg = &dis_ctx->cfg;
if(cfg->recovery_password)
memclean(cfg->recovery_password,
strlen((char*)cfg->recovery_password) + sizeof(char));
if(cfg->user_password)
memclean(cfg->user_password,
strlen((char*)cfg->user_password) + sizeof(char));
if(cfg->bek_file)
memclean(cfg->bek_file, strlen(cfg->bek_file) + sizeof(char));
if(cfg->fvek_file)
memclean(cfg->fvek_file, strlen(cfg->fvek_file) + sizeof(char));
if(cfg->vmk_file)
memclean(cfg->vmk_file, strlen(cfg->vmk_file) + sizeof(char));
if(cfg->volume_path)
dis_free(cfg->volume_path);
if(cfg->log_file)
dis_free(cfg->log_file);
}
/**
* Print read configuration
*/
void dis_print_args(dis_context_t dis_ctx)
{
if(!dis_ctx)
return;
dis_config_t* cfg = &dis_ctx->cfg;
dis_printf(L_DEBUG, "--- Config...\n");
dis_printf(L_DEBUG, " Verbosity: %d\n", cfg->verbosity);
dis_printf(L_DEBUG, " Trying to decrypt '%s'\n", cfg->volume_path);
if(cfg->decryption_mean & DIS_USE_CLEAR_KEY)
{
dis_printf(L_DEBUG, " \tusing a clear key on the volume\n");
}
else if(cfg->decryption_mean & DIS_USE_USER_PASSWORD)
{
dis_printf(L_DEBUG, " \tusing the user's password method\n");
dis_printf(L_DEBUG, " \t\t-> '%s'\n", cfg->user_password);
}
else if(cfg->decryption_mean & DIS_USE_RECOVERY_PASSWORD)
{
dis_printf(L_DEBUG, " \tusing the recovery password method\n");
dis_printf(L_DEBUG, " \t\t-> '%s'\n", cfg->recovery_password);
}
else if(cfg->decryption_mean & DIS_USE_BEKFILE)
{
dis_printf(L_DEBUG, " \tusing the bek file at '%s'\n", cfg->bek_file);
}
else if(cfg->decryption_mean & DIS_USE_FVEKFILE)
{
dis_printf(L_DEBUG, " \tusing the FVEK file at '%s'\n", cfg->fvek_file);
}
else if(cfg->decryption_mean & DIS_USE_VMKFILE)
{
dis_printf(L_DEBUG, " \tusing the VMK file at '%s'\n", cfg->vmk_file);
}
else
{
dis_printf(L_DEBUG, " \tnot using any decryption mean\n");
}
if(cfg->force_block)
dis_printf(
L_DEBUG,
" Forced to be using metadata block n°%d\n",
cfg->force_block
);
else
dis_printf(L_DEBUG, " Using the first valid metadata block\n");
if(cfg->flags & DIS_FLAG_READ_ONLY)
dis_printf(
L_DEBUG,
" Not allowing any write on the BitLocker volume "
"(read only mode)\n"
);
dis_printf(L_DEBUG, "... End config ---\n");
}
/**
* Getters for the flags
*/
int dis_is_read_only(dis_context_t dis_ctx)
{
if(!dis_ctx)
return -1;
return (dis_ctx->cfg.flags & DIS_FLAG_READ_ONLY);
}
int dis_is_volume_state_checked(dis_context_t dis_ctx)
{
if(!dis_ctx)
return -1;
return !(dis_ctx->cfg.flags & DIS_FLAG_DONT_CHECK_VOLUME_STATE);
}