Exemple #1
0
static void mount_item_proc(mount_ctx *mnt)
{
	dev_hook *hook;
	int       resl;
		
	hook = mnt->hook;
	resl = dc_mount_device(hook->dev_name, NULL, 0);

	if ( (resl != ST_RW_ERR) && (resl != ST_MEDIA_CHANGED) && (resl != ST_NO_MEDIA) ) {
		hook->mnt_probed = 1;
	}

	if (resl != ST_OK)
	{
		if (lock_inc(&hook->mnt_probe_cnt) > MAX_MNT_PROBES) {
			hook->mnt_probed = 1;
		}
	}

	if (hook->flags & F_ENABLED) {
		io_read_write_irp(hook, mnt->irp);
	} else 
	{
		if (IS_DEVICE_BLOCKED(hook) != 0) {
			dc_release_irp(hook, mnt->irp, STATUS_ACCESS_DENIED);			
		} else {
			dc_forward_irp(hook, mnt->irp);	
		}
	}
	mm_pool_free(mnt);
}
Exemple #2
0
int dc_mount_device(wchar_t *dev_name, dc_pass *password, u32 mnt_flags)
{
	dc_header *hcopy = NULL;
	dev_hook  *hook  = NULL;
	xts_key   *hdr_key = NULL;
	int        resl;
	
	DbgMsg("dc_mount_device %ws\n", dev_name);

	do 
	{
		if ( (hook = dc_find_hook(dev_name)) == NULL ) {
			resl = ST_NF_DEVICE; break;
		}

		wait_object_infinity(&hook->busy_lock);

		if (hook->flags & F_ENABLED) {
			resl = ST_ALR_MOUNT; break;
		}
		if (hook->flags & (F_UNSUPRT | F_DISABLE | F_FORMATTING)) {
			resl = ST_ERROR; break;
		}

		if ( !NT_SUCCESS(dc_fill_device_info(hook)) ) {
			resl = ST_IO_ERROR; break;
		}

		if ( ( (hook->flags & F_CDROM) && (hook->bps != CD_SECTOR_SIZE) ) ||
			 (!(hook->flags & F_CDROM) && IS_INVALID_SECTOR_SIZE(hook->bps) ) )
		{
			hook->flags |= F_UNSUPRT; resl = ST_ERROR; break;
		}
		if ( (resl = dc_probe_decrypt(hook, &hcopy, &hdr_key, password)) != ST_OK ) {
			break;
		}

		/* check volume header */		
		if ( (IS_INVALID_VOL_FLAGS(hcopy->flags) != 0) ||
			 ( (hcopy->flags & VF_STORAGE_FILE) && (hcopy->stor_off == 0) ) ||
			 (hcopy->alg_1 >= CF_CIPHERS_NUM) ||
			 (hcopy->alg_2 >= CF_CIPHERS_NUM) || 
			 (hcopy->tmp_wp_mode >= WP_NUM) ||
			 ( (hook->flags & F_CDROM) && (hcopy->flags & (VF_TMP_MODE | VF_STORAGE_FILE)) ) )
		{
			resl = ST_INV_VOLUME; break;
		}
		if (hcopy->version > DC_HDR_VERSION) {
			resl = ST_VOLUME_TOO_NEW; break;
		}
#if 0
		/* update volume header if needed */
		if ( (hcopy->version < DC_HDR_VERSION) && !(hook->flags & F_CDROM) )
		{
			hcopy->version = DC_HDR_VERSION;
			memset(hcopy->deprecated, 0, sizeof(hcopy->deprecated));
			
			io_write_header(hook, hcopy, hdr_key, NULL);
		}
#endif

		DbgMsg("hdr_key=%p, dsk_key=%p\n", hdr_key, hook->dsk_key);

		// initialize volume key
		if ( (hook->dsk_key = (xts_key*)mm_secure_alloc(sizeof(xts_key))) == NULL ) {
			resl = ST_NOMEM;
			break;
		}
		xts_set_key(hcopy->key_1, hcopy->alg_1, hook->dsk_key);

		DbgMsg("device mounted\n");

		if (hcopy->flags & VF_STORAGE_FILE) {
			hook->use_size = hook->dsk_size;
			hook->stor_off = hcopy->stor_off;
		} else {
			hook->use_size = hook->dsk_size - hook->head_len;
			hook->stor_off = hook->use_size;
		}		
		hook->crypt.cipher_id = d8(hcopy->alg_1);
		hook->disk_id    = hcopy->disk_id;
		hook->vf_version = hcopy->version;		
		hook->tmp_size   = 0;
		hook->mnt_flags  = mnt_flags;

		DbgMsg("hook->vf_version %d\n", hook->vf_version);
		DbgMsg("hook->bps %d\n", hook->bps);
		DbgMsg("hook->head_len %d\n", hook->head_len);		
		DbgMsg("flags %x\n", hcopy->flags);

		if (hcopy->flags & VF_STORAGE_FILE) {
			hook->flags |= F_PROTECT_DCSYS;
		}
		if (hcopy->flags & VF_NO_REDIR) {
			hook->flags   |= F_NO_REDIRECT;
			hook->stor_off = 0;			
		}

		if (hcopy->flags & VF_TMP_MODE)
		{
			hook->tmp_size      = hcopy->tmp_size;
			hook->hdr_key       = hdr_key;
			hook->crypt.wp_mode = hcopy->tmp_wp_mode;			

			if (hcopy->flags & VF_REENCRYPT) {
				hook->sync_init_type = S_CONTINUE_RE_ENC;
			} else {
				hook->sync_init_type = S_CONTINUE_ENC;
			}
				
			/* copy decrypted header to device data */
			memcpy(&hook->tmp_header, hcopy, sizeof(dc_header));
				
			if ( (resl = dc_enable_sync_mode(hook)) != ST_OK ) 
			{
				burn(&hook->tmp_header, sizeof(dc_header));
				hdr_key = hook->hdr_key;
			} else  {				
				hdr_key = NULL; /* prevent key wiping */
			}
		} else {			
			hook->flags |= F_ENABLED;
			resl = ST_OK;
		}
		if (resl == ST_OK) {
			/* increment mount changes counter */
			lock_inc(&hook->chg_mount);
		}
	} while (0);

	if (hdr_key != NULL) mm_secure_free(hdr_key);
	if (hcopy != NULL)   mm_secure_free(hcopy);

	if (hook != NULL)
	{
		if ((hook->flags & F_ENABLED) == 0 && hook->dsk_key != NULL) {
			mm_secure_free(hook->dsk_key);
			hook->dsk_key = NULL;
		}

		KeReleaseMutex(&hook->busy_lock, FALSE);
		dc_deref_hook(hook);
	}
	return resl;
}
Exemple #3
0
/*
   this routine process unmounting the device
   unmount options:
    UM_NOFSCTL - unmount without reporting to FS
	UM_FORCE   - force unmounting
*/
int dc_process_unmount(dev_hook *hook, int opt)
{
	IO_STATUS_BLOCK iosb;
	NTSTATUS        status;
	HANDLE          h_dev  = NULL;
	int             locked = 0;
	int             resl;	

	DbgMsg("dc_process_unmount, dev=%ws\n", hook->dev_name);
	
	if ((hook->flags & F_ENABLED) == 0)
	{
		return ST_NO_MOUNT;
	}

	wait_object_infinity(&hook->busy_lock);

	if ((hook->flags & F_ENABLED) == 0)
	{
		resl = ST_NO_MOUNT;
		goto cleanup;
	}

	do
	{
		if (hook->flags & F_FORMATTING) {
			dc_format_done(hook->dev_name);
		}

		if ( !(hook->flags & F_SYSTEM) && !(opt & MF_NOFSCTL) )
		{
			h_dev = io_open_device(hook->dev_name);

			if ( (h_dev == NULL) && !(opt & MF_FORCE) )	{
				resl = ST_LOCK_ERR; break;
			}

			if (h_dev != NULL)
			{
				status = ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);

				if ( (NT_SUCCESS(status) == FALSE) && !(opt & MF_FORCE) ) {
					resl = ST_LOCK_ERR; break;
				}
				locked = (NT_SUCCESS(status) != FALSE);

				ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);				
			}
		}

		if ((opt & MF_NOSYNC) == 0)
		{
			// temporary disable IRP processing
			hook->flags |= F_DISABLE;

			// wait for pending IRPs completion
			if ((opt & MF_NOWAIT_IO) == 0) {
				while (hook->remove_lock.Common.IoCount > 1) dc_delay(20);
			}
			if (hook->flags & F_SYNC) {
				// send signal to syncronous mode thread
				dc_send_sync_packet(hook->dev_name, S_OP_FINALIZE, 0);
			}			
		}

		hook->flags    &= ~F_CLEAR_ON_UNMOUNT;
		hook->use_size  = hook->dsk_size;
		hook->tmp_size  = 0;
		hook->mnt_flags = 0;
		resl            = ST_OK;

		// increment mount changes counter
		lock_inc(&hook->chg_mount);

		// free encryption key
		if (hook->dsk_key != NULL) {
			mm_secure_free(hook->dsk_key);
			hook->dsk_key = NULL;
		}

		if ( !(opt & MF_NOSYNC) ) {
			/* enable IRP processing */
			hook->flags &= ~F_DISABLE;
		}
	} while (0);

	if (h_dev != NULL) 
	{
		if (locked != 0) {
			ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
		}
		ZwClose(h_dev);
	}

cleanup:
	KeReleaseMutex(&hook->busy_lock, FALSE);	
	return resl;
}
Exemple #4
0
NTSTATUS dc_drv_control_irp(PDEVICE_OBJECT dev_obj, PIRP irp)
{
	PIO_STACK_LOCATION  irp_sp  = IoGetCurrentIrpStackLocation(irp);
	NTSTATUS            status  = STATUS_INVALID_DEVICE_REQUEST;
	void               *data    = irp->AssociatedIrp.SystemBuffer;
	u32                 in_len  = irp_sp->Parameters.DeviceIoControl.InputBufferLength;
	u32                 out_len = irp_sp->Parameters.DeviceIoControl.OutputBufferLength;
	u32                 code    = irp_sp->Parameters.DeviceIoControl.IoControlCode;
	u32                 bytes   = 0;
	
	switch (code)
	{
		case DC_GET_VERSION:
			{
				if (out_len == sizeof(u32)) 
				{
					p32(data)[0] = DC_DRIVER_VER;
					bytes        = sizeof(u32);
					status       = STATUS_SUCCESS;
				}
			}
		break;
		case DC_CTL_CLEAR_PASS:
			{
				dc_clean_pass_cache();
				status = STATUS_SUCCESS;
			}
		break;		
		case DC_CTL_STATUS:
			{
				dc_ioctl  *dctl = data;
				dc_status *stat = data;
				dev_hook  *hook;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_status)) )
				{
					dctl->device[MAX_DEVICE] = 0;

					if (hook = dc_find_hook(dctl->device))
					{
						if (hook->pdo_dev->Flags & DO_SYSTEM_BOOT_PARTITION) {
							hook->flags |= F_SYSTEM;
						}

						dc_get_mount_point(hook, stat->mnt_point, sizeof(stat->mnt_point));

						stat->crypt        = hook->crypt;
						stat->dsk_size     = hook->dsk_size;
						stat->tmp_size     = hook->tmp_size;
						stat->flags        = hook->flags;
						stat->mnt_flags    = hook->mnt_flags;
						stat->disk_id      = hook->disk_id;
						stat->paging_count = hook->paging_count;
						stat->vf_version   = hook->vf_version;
						status             = STATUS_SUCCESS; 
						bytes              = sizeof(dc_status);

						dc_deref_hook(hook);
					}
				}
			}
		break;
		case DC_CTL_ADD_SEED:
			{
				 if (in_len != 0) 
				 {
					 cp_rand_add_seed(data, in_len);
					 status = STATUS_SUCCESS;
					 /* prevent leaks */
					 burn(data, in_len);
				 }
			}
		break;
		case DC_CTL_GET_RAND:
			{
				dc_rand_ctl *rctl = data;
				
				if (in_len == sizeof(dc_rand_ctl))
				{
					__try
					{
						ProbeForWrite(rctl->buff, rctl->size, sizeof(u8));

						if (cp_rand_bytes(rctl->buff, rctl->size) != 0) {
							status = STATUS_SUCCESS;
						}
					} 
					__except(EXCEPTION_EXECUTE_HANDLER) {
						status = GetExceptionCode();
					}
				}
			}
		break;
		case DC_CTL_BENCHMARK:
			{
				 if ( (in_len == sizeof(int)) && (out_len == sizeof(dc_bench_info)) )
				 {
					 if (dc_k_benchmark(p32(data)[0], pv(data)) == ST_OK) {
						 status = STATUS_SUCCESS; 
						 bytes  = sizeof(dc_bench_info);
					 }
				 }
			}
		break;
		case DC_CTL_BSOD:
			{
				lock_inc(&dc_dump_disable);
				dc_clean_pass_cache();
				mm_unlock_user_memory(NULL, NULL);
				dc_clean_keys();

				KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
			}
		break;
		case DC_CTL_GET_CONF:
			{
				dc_conf *conf = data;

				if (out_len == sizeof(dc_conf)) {
					conf->conf_flags = dc_conf_flags;
					conf->load_flags = dc_load_flags;
					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_conf);
				}
			}
		break;
		case DC_CTL_SET_CONF:
			{
				dc_conf *conf = data;
				
				if (in_len == sizeof(dc_conf))
				{
					dc_conf_flags = conf->conf_flags;
					status        = STATUS_SUCCESS;

					if ( !(dc_conf_flags & CONF_CACHE_PASSWORD) ) {
						dc_clean_pass_cache();
					}
					dc_init_encryption();
				}
			}
		break;
		case DC_CTL_LOCK_MEM:
			{
				PEPROCESS    process = IoGetRequestorProcess(irp);
				dc_lock_ctl *smem = data;				

				if ( (process != NULL) && (in_len == sizeof(dc_lock_ctl)) && (out_len == in_len) ) 
				{
					smem->resl = mm_lock_user_memory(smem->data, smem->size, process);

					status = STATUS_SUCCESS; bytes = sizeof(dc_lock_ctl);
				}
			}
		break;
		case DC_CTL_UNLOCK_MEM:
			{
				PEPROCESS    process = IoGetRequestorProcess(irp);
				dc_lock_ctl *smem = data;

				if ( (process != NULL) && (in_len == sizeof(dc_lock_ctl)) && (out_len == in_len) )
				{
					mm_unlock_user_memory(smem->data, process);

					status = STATUS_SUCCESS; bytes = sizeof(dc_lock_ctl);
					smem->resl = ST_OK;
				}
			}
		break; 
		case DC_BACKUP_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_backup_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_backup_ctl);
				}
			}
		break;
		case DC_RESTORE_HEADER:
			{
				dc_backup_ctl *back = data;
				
				if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) )
				{
					back->device[MAX_DEVICE] = 0;

					back->status = dc_restore_header(back->device, &back->pass, back->backup);

					/* prevent leaks */
					burn(&back->pass, sizeof(back->pass));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_backup_ctl);
				}
			}
		break;
		default: 
			{
				dc_ioctl *dctl = data;

				if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_ioctl)) )
				{					
					/* limit null-terminated string length */
					dctl->device[MAX_DEVICE] = 0;
					
					/* process IOCTL */
					dctl->status = dc_ioctl_process(code, dctl);

					/* prevent leaks  */
					burn(&dctl->passw1, sizeof(dctl->passw1));
					burn(&dctl->passw2, sizeof(dctl->passw2));

					status = STATUS_SUCCESS;
					bytes  = sizeof(dc_ioctl);
				}
			}
		break;
	}