Example #1
0
static string_t _get_mapper_property_from_udev( const char * mapper,const char * prefix,size_t position )
{
	DIR * dir = opendir( "/dev/disk/by-id/" ) ;
	struct dirent * e ;

	const char * f = mapper + StringSize( crypt_get_dir() ) + 1 ;

	stringList_t stl ;

	string_t st = StringVoid ;

	if( dir != NULL ){

		while( ( e = readdir( dir ) ) != NULL ){

			if( StringStartsAndEndsWith( e->d_name,prefix,f ) ){

				stl = StringListSplit( e->d_name,'-' ) ;

				st = StringListCopyStringAt( stl,position ) ;

				StringListDelete( &stl ) ;

				break ;
			}
		}

		closedir( dir ) ;
	}

	return st ;
}
static int zuluExit( stringList_t stl, int status )
{
	ssize_t index ;
	switch( status ){
		case 0 : printf( gettext( "SUCCESS: Mapper created successfully\n" ) ) ;
			 index = StringListHasStartSequence( stl,crypt_get_dir() ) ;
			 if( index >= 0 ){
				 printf( gettext( "Opened mapper path: " ) ) ;
				 StringListPrintLineAt( stl,index ) ;
			 }
			 break ;
		case 1 : printf( gettext( "ERROR: Could not create mapper\n" ) )					;break ;
		case 2 : printf( gettext( "ERROR: Could not resolve device path\n" ) )					;break ;
		case 3 : printf( gettext( "\nSUCCESS: Random data successfully written\n" ) )				;break ;
		case 5 : printf( gettext( "INFO: User chose not to proceed\n" ) ) 					;break ;
		case 8 : printf( gettext( "ERROR: Insufficitied privilege to oped device \n" ) ) 			;break ;
		case 9 : printf( gettext( "ERROR: Device path is invalid\n" ) )						;break ;
		case 10: printf( gettext( "ERROR: Passphrase file does not exist\n" ) ) 				;break ;
		case 11: printf( gettext( "ERROR: Could not get enought memory to hold the key file\n" ) ) 	 	;break ;
		case 12: printf( gettext( "ERROR: Insufficient privilege to open key file for reading\n" ) )	       	;break ;
		case 13: printf( gettext( "ERROR: Can not open a mapper on a device with an opened mapper\n" ) )	;break ;
		case 14: printf( gettext( "ERROR: Can not open a mapper on a mounted device\n" ) ) 			;break ;
		case 15: printf( gettext( "INFO: Signal caught,exiting prematurely\n" ) )				;break ;
		case 16: printf( gettext( "ERROR: Can not get passphrase in silent mode\n" ) )				;break ;
		case 17: printf( gettext( "ERROR: Insufficient memory to hold passphrase\n" ) ) 			;break ;
		case 18: printf( gettext( "ERROR: Insufficient memory to hold 3 characters?really?\n" ) ) 		;break ;
		case 19: printf( gettext( "ERROR: Insufficient privilege to open the file with your privileges?\n" ) )  ;break ;
	}

	StringListClearDelete( &stl ) ;
	return status ;
}
Example #3
0
static char * _volume_device_name( const char * mapper,char * ( *function )( const char * ) )
{
	struct crypt_device * cd ;
	const char * e = crypt_get_dir() ;
	char * f = NULL ;

	if( zuluCryptTrueCryptOrVeraCryptVolume( mapper ) ){

		return _device_name( mapper,function ) ;
	}else{
		if( crypt_init_by_name( &cd,mapper ) == 0 ){

			e = crypt_get_device_name( cd ) ;

			if( e != NULL ){

				f = function( e ) ;
			}

			crypt_free( cd ) ;
		}

		return f ;
	}
}
Example #4
0
static int _wipe_data_device(struct crypt_device *cd, const char *integrity_key)
{
	char tmp_name[64], tmp_path[128], tmp_uuid[40];
	uuid_t tmp_uuid_bin;
	int r;

	if (!opt_batch_mode)
		log_std(_("Wiping device to initialize integrity checksum.\n"
			"You can interrupt this by pressing CTRL+c "
			"(rest of not wiped device will contain invalid checksum).\n"));

	/* Activate the device a temporary one */
	uuid_generate(tmp_uuid_bin);
	uuid_unparse(tmp_uuid_bin, tmp_uuid);
	if (snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid) < 0)
		return -EINVAL;
	if (snprintf(tmp_path, sizeof(tmp_path), "%s/%s", crypt_get_dir(), tmp_name) < 0)
		return -EINVAL;

	r = crypt_activate_by_volume_key(cd, tmp_name, integrity_key,
		opt_integrity_key_size, CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL);
	if (r < 0)
		return r;

	/* Wipe the device */
	set_int_handler(0);
	r = crypt_wipe(cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, DEFAULT_WIPE_BLOCK,
		       0, &tools_wipe_progress, NULL);
	if (crypt_deactivate(cd, tmp_name))
		log_err(_("Cannot deactivate temporary device %s."), tmp_path);
	set_int_block(0);

	return r;
}
Example #5
0
static int _create_volume( const char * dev,const char * fs,const char * type,const char * pass,size_t pass_size,const char * rng )
{
	size_t len ;
	int status ;
	
	string_t m = StringVoid ;
	
	const char * device_mapper ;
	const char * mapper ;
	
	if ( zuluCryptPathIsNotValid( dev ) ){
		return 1 ;
	}
		
	m = String( crypt_get_dir() ) ;
	len = StringLength( m )   ;
	
	StringAppend( m,"/zuluCrypt-" ) ;
	device_mapper = StringAppendInt( m,syscall( SYS_gettid ) ) ;
	mapper = device_mapper + len + 1 ;
		
	if( StringsAreEqual( type,"luks" ) ){
		if( StringsAreNotEqual( rng,"/dev/random" ) ){
			if( StringsAreNotEqual( rng,"/dev/urandom" ) ){
				return zuluExit( 2,m ) ; 
			}
		}
		if( zuluCryptCreateLuks( dev,pass,pass_size,rng ) != 0 ){
			return zuluExit( 3,m ) ;
		}
		if( zuluCryptOpenLuks( dev,mapper,"rw",pass,pass_size ) != 0 ){
			return zuluExit( 3,m ) ; 
		}
	}else if( StringsAreEqual( type,"plain") ){
		if( zuluCryptOpenPlain( dev,mapper,"rw",pass,pass_size ) != 0 ){
			return zuluExit( 3,m ) ; 
		}
	}else{
		return zuluExit( 2,m ) ;
	}
	
	status = zuluCryptCreateFileSystemInAVolume( fs,device_mapper ) ;
	/*
	 * zuluCryptCloseMapper() is defined in close_mapper.c
	 */
	zuluCryptCloseMapper( device_mapper );
	
	if( status == 0 ){
		return zuluExit( 0,m ) ;
	}else{
		return zuluExit( 3,m ) ;
	}
}
Example #6
0
static int _create_file_system( const char * device,const char * fs,int key_source,
				const char * key,size_t key_len,int volume_type )
{
	string_t m = StringVoid ;

	int r ;

	const char * device_mapper ;
	const char * mapper ;

	size_t len ;

	m = String( crypt_get_dir() ) ;
	len = StringLength( m )   ;

	StringAppend( m,"/zuluCrypt-" ) ;
	device_mapper = StringAppendInt( m,syscall( SYS_gettid ) ) ;
	mapper = device_mapper + len + 1 ;

	/*
	 * zuluCryptOpenTcrypt() is defined in open_tcrypt.c
	 */
	if( zuluCryptOpenTcrypt( device,mapper,key,key_len,key_source,volume_type,NULL,0,0,NULL ) == 0 ){
		/*
		 * zuluCryptCreateFileSystemInAVolume() is defined in create_volume.c
		 */
		if( zuluCryptCreateFileSystemInAVolume( fs,device_mapper ) == 0 ){
			r = 0 ;
		}else{
			r = 3 ;
		}
		/*
		 * zuluCryptCloseMapper() is defined in close_mapper.c
		 */
		zuluCryptCloseMapper( device_mapper ) ;
	}else{
		r = 3 ;
	}

	StringDelete( &m ) ;
	return r ;
}
Example #7
0
char * zuluCryptGetVolumeTypeFromMapperPath( const char * mapper )
{
	struct crypt_device * cd ;
	const char * type ;
	char * r ;
	string_t st ;

	if( StringPrefixNotEqual( mapper,crypt_get_dir() ) ){

		return StringCopy_2( "Nil" ) ;
	}

	if( crypt_init_by_name( &cd,mapper ) < 0 ){

		return StringCopy_2( "Nil" ) ;
	}

	type = crypt_get_type( cd ) ;

	if( type == NULL ){

		if( StringHasComponent( mapper,"veracrypt" ) ){

			r = StringCopy_2( "crypto_VCRYPT" ) ;

		}else if( StringHasComponent( mapper,"truecrypt" ) ){

			r = StringCopy_2( "crypto_TCRYPT" ) ;
		}else{
			r = _get_type_from_udev( mapper ) ;
		}
	}else{
		st = String_1( "crypto_",type,NULL ) ;
		r = StringDeleteHandle( &st ) ;
	}

	crypt_free( cd ) ;
	return r ;
}
Example #8
0
void checkForOpenedMappers( void )
{
	char * d ;
	
	int st = 1 ;
	
	struct dirent * entry ;
	
	DIR * dir = opendir( crypt_get_dir() ) ;
	
	printf( "check if there are no opened mappers: " ) ;
	
	if( dir == NULL ){
		printf( "failed to complete the test\n" ) ;
		EXIT( 1,NULL ) ;
	}
		
	while( ( entry = readdir( dir ) ) != NULL ){
		
		d = strstr( entry->d_name,"zuluCrypt-" ) ;
		if( d != NULL ){
			if( st ){
				printf( "FAILED\n" ) ;
				st = 0 ;
			}
			st = 0 ;
			printf( "found opened mapper: /dev/mapper/%s\n",entry->d_name ) ;
		}
	}
	
	closedir( dir ) ;
	
	if( st ){
		printf( "PASSED\n" ) ;
	}
}
Example #9
0
static int activate_and_check_status(const char *path, const char *device_name)
{
	struct crypt_device *cd;
	struct crypt_active_device cad;
	int r;

	/*
	 * LUKS device activation example.
	 * It's sequence of sub-steps: device initialization, LUKS header load
	 * and the device activation itself.
	 */
	r = crypt_init(&cd, path);
	if (r < 0 ) {
		printf("crypt_init() failed for %s.\n", path);
		return r;
	}

	/*
	 * crypt_load() is used to load the LUKS header from block device
	 * into crypt_device context.
	 */
	r = crypt_load(cd,		/* crypt context */
		       CRYPT_LUKS1,	/* requested type */
		       NULL);		/* additional parameters (not used) */

	if (r < 0) {
		printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
		crypt_free(cd);
		return r;
	}

	/*
	 * Device activation creates device-mapper devie mapping with name device_name.
	 */
	r = crypt_activate_by_passphrase(cd,		/* crypt context */
					 device_name,	/* device name to activate */
					 CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
					 "foo", 3,	/* passphrase */
					 CRYPT_ACTIVATE_READONLY); /* flags */
	if (r < 0) {
		printf("Device %s activation failed.\n", device_name);
		crypt_free(cd);
		return r;
	}

	printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
	printf("\tcipher used: %s\n", crypt_get_cipher(cd));
	printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
	printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));

	/*
	 * Get info about active device (query DM backend)
	 */
	r = crypt_get_active_device(cd, device_name, &cad);
	if (r < 0) {
		printf("Get info about active device %s failed.\n", device_name);
		crypt_deactivate(cd, device_name);
		crypt_free(cd);
		return r;
	}

	printf("Active device parameters for %s:\n"
		"\tDevice offset (in sectors): %" PRIu64 "\n"
		"\tIV offset (in sectors)    : %" PRIu64 "\n"
		"\tdevice size (in sectors)  : %" PRIu64 "\n"
		"\tread-only flag            : %s\n",
		device_name, cad.offset, cad.iv_offset, cad.size,
		cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");

	crypt_free(cd);
	return 0;
}
Example #10
0
static int action_format(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {
		.journal_size = opt_journal_size,
		.interleave_sectors = opt_interleave_sectors,
		/* in bitmap mode we have to overload these values... */
		.journal_watermark = opt_integrity_bitmap ? opt_bitmap_sectors_per_bit : opt_journal_watermark,
		.journal_commit_time = opt_integrity_bitmap ? opt_bitmap_flush_time : opt_journal_commit_time,
		.buffer_sectors = opt_buffer_sectors,
		.tag_size = opt_tag_size,
		.sector_size = opt_sector_size ?: SECTOR_SIZE,
	};
	char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
	char *integrity_key = NULL, *msg = NULL;
	int r;
	size_t signatures;

	if (opt_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_integrity, integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.integrity = integrity;
	}

	if (opt_journal_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_journal_integrity, journal_integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_integrity = journal_integrity;
	}

	if (opt_journal_crypt) {
		r = crypt_parse_hash_integrity_mode(opt_journal_crypt, journal_crypt);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_crypt = journal_crypt;
	}

	r = _read_keys(&integrity_key, &params);
	if (r)
		goto out;

	r = crypt_init_data_device(&cd, action_argv[0], opt_data_device);
	if (r < 0)
		goto out;

	r = asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]);
	if (r == -1) {
		r = -ENOMEM;
		goto out;
	}

	r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
	free(msg);
	if (r < 0)
		goto out;

	r = tools_detect_signatures(action_argv[0], 0, &signatures);
	if (r < 0)
		goto out;

	/* Signature candidates found */
	if (signatures && ((r =	tools_wipe_all_signatures(action_argv[0])) < 0))
		goto out;

	r = crypt_format(cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, &params);
	if (r < 0) /* FIXME: call wipe signatures again */
		goto out;

	if (!opt_batch_mode)
		log_std(_("Formatted with tag size %u, internal integrity %s.\n"), opt_tag_size, opt_integrity);

	if (!opt_no_wipe)
		r = _wipe_data_device(cd, integrity_key);
out:
	crypt_safe_free(integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
	crypt_free(cd);
	return r;
}

static int action_open(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {
		/* in bitmap mode we have to overload these values... */
		.journal_watermark = opt_integrity_bitmap ? opt_bitmap_sectors_per_bit : opt_journal_watermark,
		.journal_commit_time = opt_integrity_bitmap ? opt_bitmap_flush_time : opt_journal_commit_time,
		.buffer_sectors = opt_buffer_sectors,
	};
	uint32_t activate_flags = 0;
	char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
	char *integrity_key = NULL;
	int r;

	if (opt_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_integrity, integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.integrity = integrity;
	}

	if (opt_journal_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_journal_integrity, journal_integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;

		}
		params.journal_integrity = journal_integrity;
	}

	if (opt_journal_crypt) {
		r = crypt_parse_hash_integrity_mode(opt_journal_crypt, journal_crypt);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_crypt = journal_crypt;
	}

	if (opt_integrity_nojournal || opt_integrity_bitmap)
		activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
	if (opt_integrity_recovery)
		activate_flags |= CRYPT_ACTIVATE_RECOVERY;
	if (opt_integrity_bitmap)
		activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;

	if (opt_integrity_recalculate)
		activate_flags |= CRYPT_ACTIVATE_RECALCULATE;

	r = _read_keys(&integrity_key, &params);
	if (r)
		goto out;

	if ((r = crypt_init_data_device(&cd, action_argv[0], opt_data_device)))
		goto out;

	r = crypt_load(cd, CRYPT_INTEGRITY, &params);
	if (r)
		goto out;

	r = crypt_activate_by_volume_key(cd, action_argv[1], integrity_key,
					 opt_integrity_key_size, activate_flags);
out:
	crypt_safe_free(integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
	crypt_free(cd);
	return r;
}

static int action_close(int arg)
{
	struct crypt_device *cd = NULL;
	int r;

	r = crypt_init_by_name(&cd, action_argv[0]);
	if (r == 0)
		r = crypt_deactivate(cd, action_argv[0]);

	crypt_free(cd);
	return r;
}

static int action_status(int arg)
{
	crypt_status_info ci;
	struct crypt_active_device cad;
	struct crypt_params_integrity ip = {};
	struct crypt_device *cd = NULL;
	char *backing_file;
	const char *device, *metadata_device;
	int path = 0, r = 0;

	/* perhaps a path, not a dm device name */
	if (strchr(action_argv[0], '/'))
		path = 1;

	ci = crypt_status(NULL, action_argv[0]);
	switch (ci) {
	case CRYPT_INVALID:
		r = -EINVAL;
		break;
	case CRYPT_INACTIVE:
		if (path)
			log_std("%s is inactive.\n", action_argv[0]);
		else
			log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
		r = -ENODEV;
		break;
	case CRYPT_ACTIVE:
	case CRYPT_BUSY:
		if (path)
			log_std("%s is active%s.\n", action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");
		else
			log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");

		r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
		if (r < 0)
			goto out;

		log_std("  type:    %s\n", crypt_get_type(cd) ?: "n/a");

		r = crypt_get_active_device(cd, action_argv[0], &cad);
		if (r < 0)
			goto out;

		r = crypt_get_integrity_info(cd, &ip);
		if (r < 0)
			goto out;

		log_std("  tag size: %u\n", ip.tag_size);
		log_std("  integrity: %s\n", ip.integrity ?: "(none)");
		device = crypt_get_device_name(cd);
		metadata_device = crypt_get_metadata_device_name(cd);
		log_std("  device:  %s%s\n", device, metadata_device ? " (detached)" : "");
		if (crypt_loop_device(device)) {
			backing_file = crypt_loop_backing_file(device);
			log_std("  loop:    %s\n", backing_file);
			free(backing_file);
		}
		if (metadata_device) {
			log_std("  metadata device:  %s\n", metadata_device);
			if (crypt_loop_device(metadata_device)) {
				backing_file = crypt_loop_backing_file(metadata_device);
				log_std("  loop:    %s\n", backing_file);
				free(backing_file);
			}
		}
		log_std("  sector size:  %u bytes\n", crypt_get_sector_size(cd));
		log_std("  interleave sectors: %u\n", ip.interleave_sectors);
		log_std("  size:    %" PRIu64 " sectors\n", cad.size);
		log_std("  mode:    %s%s\n",
			cad.flags & CRYPT_ACTIVATE_READONLY ? "readonly" : "read/write",
			cad.flags & CRYPT_ACTIVATE_RECOVERY ? " recovery" : "");
		log_std("  failures: %" PRIu64 "\n",
			crypt_get_active_integrity_failures(cd, action_argv[0]));
		if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) {
			log_std("  bitmap 512-byte sectors per bit: %u\n", ip.journal_watermark);
			log_std("  bitmap flush interval: %u ms\n", ip.journal_commit_time);
		} if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL) {
			log_std("  journal: not active\n");
		} else {
			log_std("  journal size: %" PRIu64 " bytes\n", ip.journal_size);
			log_std("  journal watermark: %u%%\n", ip.journal_watermark);
			log_std("  journal commit time: %u ms\n", ip.journal_commit_time);
			if (ip.journal_integrity)
				log_std("  journal integrity MAC: %s\n", ip.journal_integrity);
			if (ip.journal_crypt)
				log_std("  journal encryption: %s\n", ip.journal_crypt);
		}
	}
out:
	crypt_free(cd);
	if (r == -ENOTSUP)
		r = 0;
	return r;
	return -EINVAL;
}

static int action_dump(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {};
	int r;

	if ((r = crypt_init(&cd, action_argv[0])))
		return r;

	r = crypt_load(cd, CRYPT_INTEGRITY, &params);
	if (!r)
		crypt_dump(cd);

	crypt_free(cd);
	return r;
}

static struct action_type {
	const char *type;
	int (*handler)(int);
	int required_action_argc;
	const char *arg_desc;
	const char *desc;
} action_types[] = {
	{ "format",	action_format, 1, N_("<integrity_device>"),N_("format device") },
	{ "open",	action_open,   2, N_("<integrity_device> <name>"),N_("open device as <name>") },
	{ "close",	action_close,  1, N_("<name>"),N_("close device (deactivate and remove mapping)") },
	{ "status",	action_status, 1, N_("<name>"),N_("show active device status") },
	{ "dump",	action_dump,   1, N_("<integrity_device>"),N_("show on-disk information") },
	{ NULL, NULL, 0, NULL, NULL }
};

static void help(poptContext popt_context,
		 enum poptCallbackReason reason __attribute__((unused)),
		 struct poptOption *key,
		 const char *arg __attribute__((unused)),
		 void *data __attribute__((unused)))
{
	struct action_type *action;

	if (key->shortName == '?') {
		log_std("%s %s\n", PACKAGE_INTEGRITY, PACKAGE_VERSION);
		poptPrintHelp(popt_context, stdout, 0);
		log_std(_("\n"
			 "<action> is one of:\n"));
		for(action = action_types; action->type; action++)
			log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
		log_std(_("\n"
			 "<name> is the device to create under %s\n"
			 "<integrity_device> is the device containing data with integrity tags\n"),
			crypt_get_dir());

		log_std(_("\nDefault compiled-in dm-integrity parameters:\n"
			  "\tTag size: %u bytes, Checksum algorithm: %s\n"),
			  DEFAULT_TAG_SIZE, DEFAULT_ALG_NAME);
		exit(EXIT_SUCCESS);
	} else
		usage(popt_context, EXIT_SUCCESS, NULL, NULL);
}

static int run_action(struct action_type *action)
{
	int r;

	log_dbg("Running command %s.", action->type);

	r = action->handler(0);

	show_status(r);
	return translate_errno(r);
}
static int open_plain_as_me_1(const struct_opts * opts,const char * mapping_name,uid_t uid,int op )
{
	/*
	 * Below is a form of memory management.All strings are collected in a stringlist object to easily delete them
	 * when the function returns.This allows for the function to have multiple exit points without risks of leaking
	 * memory from manually examining each exit point to make sure all strings are deleted or go with multiple goto
	 * code deleting blocks to take into account different exit points.
	 */
	stringList_t stl ;
	string_t * stringArray  = StringListArray( &stl,5 ) ;
	string_t * mapper     = &stringArray[ 0 ] ;
	string_t * passphrase = &stringArray[ 1 ] ;
	string_t * p          = &stringArray[ 2 ] ;
	string_t * dev_st     = &stringArray[ 3 ] ;
	string_t * dev_1      = &stringArray[ 4 ] ;

	size_t len = 0 ;

	const char * source      = opts->key_source ;
	const char * pass        = opts->key ;

	int k = opts->ask_confirmation ;

	const char * cpass = NULL ;

	char * d ;

	const char * device = opts->device ;
	const char * dev = opts->device ;

	int j ;
	int n ;

	const char * cmapper ;

	if( StringPrefixEqual( device,"/dev/loop" ) ){
		/*
		 * zuluCryptLoopDeviceAddress() is defined in ../lib/create_loop_device.c
		 */
		d = zuluCryptLoopDeviceAddress( device ) ;
		*dev_st = StringInherit( &d ) ;
		dev = StringContent( *dev_st ) ;
		*dev_1 = StringCopy( *dev_st ) ;
		device = StringReplaceString( * dev_1,"\\040"," " ) ;
	}

	/*
	 * zuluCryptPartitionIsSystemPartition() is defined in ./partition.c
	 */
	if( zuluCryptPartitionIsSystemPartition( device,uid ) ){
		if( uid != 0 ){
			return zuluExit( stl,8 ) ;
		}
	}
	/*
	 * ZULUCRYPTlongMapperPath and ZULUCRYPTshortMapperPath are in ../constants.h
	 * zuluCryptCreateMapperName() is defined at ../lib/create_mapper_name.c
	 */
	*mapper = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTshortMapperPath ) ;

	*p = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTlongMapperPath ) ;

	j = zuluCryptCheckOpenedMapper( StringContent( *p ) ) ;

	/*
	 * zuluCryptPartitionIsMounted() is defined in ../lib/process_mountinfo.c
	 */
	n = zuluCryptPartitionIsMounted( dev ) ;

	if( j == 1 ){
		return zuluExit( stl,13 ) ;
	}
	if( n == 1 ){
		return zuluExit( stl,14 ) ;
	}
	if( k == 0 ){
		*passphrase = StringRandomString( 64 ) ;
		cpass = StringContent( *passphrase ) ;
		len = StringLength( *passphrase ) ;
	}else if( source == NULL ){
		printf( gettext( "Enter passphrase: " ) ) ;
		/*
		 * ZULUCRYPT_KEY_MAX_SIZE is set in ../constants.h
		 */
		switch( StringSilentlyGetFromTerminal_1( passphrase,ZULUCRYPT_KEY_MAX_SIZE ) ){
			case 1 : return zuluExit( stl,16 ) ;
			case 2 : return zuluExit( stl,17 ) ;
		}
		printf( "\n" ) ;
		cpass = StringContent( *passphrase ) ;
		len = StringLength( *passphrase ) ;
	}else{
		if( strcmp( source,"-p" ) == 0 ){
			*passphrase = String( pass ) ;
			cpass = StringContent( *passphrase ) ;
			len = StringLength( *passphrase ) ;
		}else if( strcmp( source,"-f" ) == 0 ){
			/*
			 * zuluCryptGetPassFromFile() is defined at "path_access.c"
			 */
			switch( zuluCryptGetPassFromFile( pass,uid,passphrase ) ){
				case 1 : return zuluExit( stl,10 ) ;
				case 2 : return zuluExit( stl,11 ) ;
				case 4 : return zuluExit( stl,12 ) ;
			}
			cpass = StringContent( *passphrase ) ;
			len = StringLength( *passphrase ) ;
		}
	}

	if( zuluCryptSecurityGainElevatedPrivileges() ){
		/*
		 * zuluCryptOpenPlain() is defined in ../lib/open_plain.c
		 */
		if( zuluCryptOpenPlain( device,StringContent( *mapper ),"rw",cpass,len ) != 0 ){
			zuluCryptSecurityDropElevatedPrivileges() ;
			return zuluExit( stl,1 ) ;
		}
	}

	zuluCryptSecurityDropElevatedPrivileges() ;

	/*
	 * Create a mapper path(usually at /dev/mapper) associated with opened plain mapper above.
	 */
	cmapper = StringMultiplePrepend( *mapper,"/",crypt_get_dir(),NULL ) ;

	/*
	 *  mapper path is usually a soft link to /dev/dm-X
	 *  resolve the mapper path to its respective /dev/dm-X and set permission on it.
	 *
	 * We set permission of /dev/dm-X pointing to the device to "u+rw" because we want notmal user to be able
	 * to write to the device through the mapper.
	 *
	 * Useful when a normal user want to delete content of the device by writing random data to it.
	 */
	d = zuluCryptRealPath( cmapper ) ;
	if( zuluCryptSecurityGainElevatedPrivileges() ){
		if( d != NULL ){
			_ignore_result( chown( d,uid,0 ) ) ;
			_ignore_result( chmod( d,S_IRWXU ) ) ;
			StringFree( d ) ;
		}
		zuluCryptSecurityDropElevatedPrivileges() ;
	}else{
		return zuluExit( stl,1 ) ;
	}

	if( op == 1 ){
		return zuluExit( stl,0 ) ;
	}else{
		StringListClearDelete( &stl ) ;
		return 0 ;
	}
}
/*
 * Purpose of this function is to open a device and write random data to it as a way of hiding information on the disk.
 *
 * The above is accomplished by opening a plain mapper against the device and then write to the device through the mapper
 *
 */
int zuluCryptEXEWriteDeviceWithJunk( const struct_opts * opts,const char * mapping_name,uid_t uid )
{
	stringList_t stl   = StringListInit() ;
	string_t * mapper  = StringListAssign( stl ) ;
	string_t * confirm = StringListAssign( stl );

	double size ;
	double size_written ;

	const char * device =  opts->device ;

	char buffer[ SIZE ] ;

	int ratio ;
	int prev_ratio ;
	int k ;

	struct sigaction sigac;

	memset( &sigac,'\0',sizeof( struct sigaction ) ) ;

	sigac.sa_handler = &sigTERMhandler ;

	sigaction( SIGINT,&sigac,NULL ) ;
	sigaction( SIGTERM,&sigac,NULL ) ;
	sigaction( SIGHUP,&sigac,NULL ) ;

	__exit_as_requested = 0 ;

	if( ( k = open_plain_as_me_1( opts,mapping_name,uid,0 ) ) != 0 ){
		return k ;
	}
	*mapper = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTshortMapperPath ) ;

	StringMultiplePrepend( *mapper,"/",crypt_get_dir(),NULL ) ;

	if( opts->ask_confirmation ){
		printf( gettext( "\nWARNING, device \"%s\" will be overwritten with random data destroying all present data.\n" ),device ) ;
		printf( gettext( "Are you sure you want to proceed? Type \"YES\" and press enter if you are sure: " ) ) ;

		*confirm = StringGetFromTerminal_1( 3 ) ;
		if( *confirm == StringVoid ){
			return zuluExit( stl,17 ) ;
		}else{
			k = StringEqual( *confirm,gettext( "YES" ) ) ;

			if( k == 0 ){
				if( zuluCryptSecurityGainElevatedPrivileges() ){
					zuluCryptCloseMapper( StringContent( *mapper ) ) ;
					zuluCryptSecurityDropElevatedPrivileges() ;
				}
				return zuluExit( stl,5 ) ;
			}
		}
	}

	k = open( StringContent( *mapper ),O_WRONLY ) ;

	size = ( double ) blkid_get_dev_size( k ) ;

	memset( buffer,0,SIZE ) ;

	size_written = 0 ;
	prev_ratio = -1 ;

	while( write( k,buffer,SIZE ) > 0 ){

		if( __exit_as_requested == 1 ){
			break ;
		}
		size_written += SIZE ;

		ratio = ( int ) ( ( size_written / size ) * 100 ) ;

		if( ratio > prev_ratio ){
			printf( "\r%s %d%%",gettext( "percentage complete: " ),ratio ) ;
			fflush( stdout );
			prev_ratio = ratio ;
		}
	}

	close( k ) ;
	if( zuluCryptSecurityGainElevatedPrivileges() ){
		zuluCryptCloseMapper( StringContent( *mapper ) ) ;
		zuluCryptSecurityDropElevatedPrivileges() ;
	}

	if( __exit_as_requested == 1 ){
		return zuluExit( stl,15 ) ;
	}else{
		return zuluExit( stl,3 ) ;
	}
}