⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cli.c

📁 完美的虚拟加密文件系统程序。可以加密硬盘、优盘等
💻 C
📖 第 1 页 / 共 5 页
字号:

		if (fgets (s, sizeof (s), stdin) && sscanf (s, "%d", &c) == 1)
		{
			if (c < min || c > max)
				continue;

			puts ("");
			return c;
		}

		puts ("");
		return defaultChoice;
	}
}


static char *AskString (char *prompt, char *buf, int maxSize)
{
	printf ("%s: ", prompt);

	if (fgets (buf, maxSize, stdin))
	{
		char *lf = strchr (buf, '\n');
		if (lf)
			lf[0] = 0;

		return buf;
	}

	return NULL;
}


static void AskPassword (char *prompt, char *volumePath, Password *password)
{
	struct termios noEcho;

	if (tcgetattr (0, &TerminalAttributes) == 0)
	{
		noEcho = TerminalAttributes;

		if (!DisplayPassword)
		{
			noEcho.c_lflag &= ~ECHO;
			if (tcsetattr (0, TCSANOW, &noEcho) != 0)
				error ("Failed to turn terminal echo off\n");
		}

		printf (prompt, volumePath);
	}

	if (fgets ((char *)password->Text, sizeof (password->Text), stdin))
	{
		char *newl = strchr ((char *)password->Text, '\n');
		if (newl) newl[0] = 0;

		password->Length = strlen ((char *)password->Text);
	}
	else
		password->Length = 0;

	if (IsTerminal && !DisplayPassword)
	{
		tcsetattr (0, TCSANOW, &TerminalAttributes);
		puts ("");
	}
}


static char *AskVolumePath (char *volumePath, char *prompt)
{
	static char path[MAX_PATH];

	// Volume path
	while (!volumePath || !volumePath[0])
	{
		volumePath = AskString (prompt, path, sizeof (path));
	}

	return volumePath;
}


static BOOL OpenVolume (char *volumePath, char *prompt, char *promptArg, BOOL secondaryPassword, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime)
{
	char header[SECTOR_SIZE];
	uint64_t r;
	FILE *f = NULL;
	struct stat volumeStat;
	int tries = PasswordEntryTries;
	char msg[128];
	BOOL ret = FALSE;

	if (stat (volumePath, &volumeStat) != 0)
	{
		perror ("Cannot read volume's modification and access time");
		volumeStat.st_ctime = 0;
		goto err;
	}

	f = fopen (volumePath, "rb");
	if (!f)
	{
		perror ("Cannot open volume");
		goto err;
	}

	do
	{
		Password *pw = &password;

		if (!secondaryPassword && !CmdPasswordValid || (secondaryPassword && !CmdPassword2Valid))
			AskPassword (prompt, promptArg, &password);
		else
			pw = secondaryPassword ? &CmdPassword2 : &CmdPassword;

		if ((!secondaryPassword
				&& FirstKeyFile
				&& !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
			|| (secondaryPassword 
				&& FirstProtVolKeyFile
				&& !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime)))
		{
			error ("Error while processing keyfiles\n");
			goto err;
		}

		// Normal header
		fseek (f, 0, SEEK_SET);
		if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
		{
			perror ("Cannot read volume header");
			goto err;
		}

		if (fseek (f, 0, SEEK_END) == -1)
		{
			perror ("Cannot determine volume size");
			goto err;
		}

		r = VolumeReadHeader (header, pw, cryptoInfo);

		if (r == 0)
		{
			*totalSectors = ftello (f) / SECTOR_SIZE - 1;
			*startSector = 1;
			ret = TRUE;
			break;
		}

		if (r == ERR_PASSWORD_WRONG)
		{
			// Hidden header
			if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1
				|| fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
			{
				perror ("Cannot read volume header");
				goto err;
			}

			r = VolumeReadHeader (header, pw, cryptoInfo);

			if (r == 0)
			{
				*startSector = (ftello (f) 
					+ SECTOR_SIZE * 2 
					- (*cryptoInfo)->hiddenVolumeSize 
					- HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;

				*totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
				ret = TRUE;
				break;
			}
			
			if (r == ERR_PASSWORD_WRONG)
			{
				if (IsTerminal)
				{
					puts ("Incorrect password or not a TrueCrypt volume.");
					continue;
				}
				else
				{
					error ("Incorrect password or not a TrueCrypt volume.\n");
					goto err;
				}
			}
		}

		// Report errors
		switch (r)
		{
		case ERR_NEW_VERSION_REQUIRED:
			strcpy (msg, "A newer version of TrueCrypt is required to open this volume."); 
			break;

		default:
			sprintf (msg, "Volume cannot be opened: Error %d", r);
			break;
		}

		if (IsTerminal)
			printf ("%s\n", msg);
		else
			error ("%s\n", msg);

		goto err;

	} while (IsTerminal
		&& --tries > 0
		&& ((!secondaryPassword && !CmdPasswordValid)
			|| (secondaryPassword && !CmdPassword2Valid)));

	fclose (f);

	if (!UpdateTime)
		RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);

	*modTime = volumeStat.st_mtime;
	*acTime = volumeStat.st_atime;

	return ret;

err:
	*cryptoInfo = NULL;

	if (f)
		fclose (f);

	if (volumeStat.st_ctime != 0 && !UpdateTime)
		RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);

	*totalSectors = 0;
	return FALSE;
}


static char *EscapeSpaces (char *string)
{
	static char escapedString[MAX_PATH * 2];
	char *e = escapedString;
	char c;

	if (strlen (string) > MAX_PATH)
		return NULL;

	while ((c = *string++))
	{
		if (c == ' ')
			*e++ = '\\';

		*e++ = c;
	}

	return escapedString;
}


static BOOL MountVolume (char *volumePath, char *mountPoint)
{
	char hostDevice[MAX_PATH];
	char mapDevice[MAX_PATH];
	int loopDevNo = -1;
	PCRYPTO_INFO ci = NULL;
	uint64_t startSector, totalSectors;
	uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
	int pfd[2];
	int pid, res, devNo;
	time_t modTime, acTime;
	FILE *f, *w;
	int flags;
	int i;
	int tries = PasswordEntryTries;

#if DEBUG
	if (!AutoTestAlgorithms ())
	{
		error ("Self-tests of algorithms FAILED!\n");
		return FALSE;
	}
#endif

	if (IsVolumeMounted (volumePath))
	{
		error ("Volume already mapped\n");
		return FALSE;
	}

	if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE,
		&ci, &startSector, &totalSectors, &modTime, &acTime))
		goto err;

	if (totalSectors == 0)
	{
		error ("Illegal volume size (0 bytes).\n");
		goto err;
	}

	// Hidden volume protection
	if (ProtectHidden)
	{
		PCRYPTO_INFO ciH = NULL;
		uint64_t startSectorH, totalSectorsH;

		if (OpenVolume (volumePath, "Enter hidden volume password: ", "", TRUE,
			&ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
		{
			readOnlyStartSector = startSectorH;
			readOnlySectors = startSectorH + totalSectorsH;
		}
		
		if (ciH)
			crypto_close (ciH);

		if (readOnlySectors == 0)
			goto err;
	}

	// Headers decrypted

	// Loopback
	if (IsFile (volumePath))
	{
		int i;

		for (i = 0; i < MAX_MINOR; i++)
		{
			snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);

			if (!IsBlockDevice (hostDevice))
			{
				snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
				if (!IsBlockDevice (hostDevice))
					continue;
			}

			if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
				break;
		}

		if (i >= MAX_MINOR)
		{
			error ("No free loopback device available for file-hosted volume\n");
			goto err;
		}

		loopDevNo = i;

		if (Verbose > 1)
			printf ("Attached %s to %s\n", volumePath, hostDevice);

	}
	else
		strncpy (hostDevice, volumePath, sizeof (hostDevice));

	// Load kernel module
	if (!LoadKernelModule ())
		goto err;

	if (!CheckKernelModuleVersion (TRUE))
		goto err;

	// dmsetup
	devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
	if (devNo == -1)
	{
		error ("Maximum number of volumes mounted\n");
		goto err;
	}

	sprintf (mapDevice, "truecrypt%d", devNo);

	pipe (pfd);
	pid = fork ();

	if (pid == -1)
	{
		perror ("fork");
		goto err;
	}
	else if (pid == 0)
	{
		SecurityCleanup ();

		close (pfd[1]);
		dup2 (pfd[0], STDIN_FILENO);

		execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);

		perror ("execlp dmsetup");
		_exit (1);
	}

	close (pfd[0]);
	w = fdopen (pfd[1], "a");
	if (w == NULL)
	{
		perror ("fdopen");
		goto err;
	}

	fprintf (w, "0 %lld truecrypt %d %d ", totalSectors, ci->ea, ci->mode);

	for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
		fprintf (w, "%02x", ci->master_key[i]);

	fprintf (w, " ");

	for (i = 0; i < (int)sizeof (ci->iv); i++)
		fprintf (w, "%02x", ci->iv[i]);

	flags = 0;

	if (ReadOnly)
		flags |= FLAG_READ_ONLY;
	else if (ProtectHidden)
		flags |= FLAG_HIDDEN_VOLUME_PROTECTION;

	fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
		hostDevice,
		startSector,
		readOnlyStartSector,
		readOnlySectors,
		(uint64_t) modTime,
		(uint64_t) acTime,
		flags,
		EscapeSpaces (volumePath));

	fclose (w);

	if (!WaitChild (FALSE, "dmsetup"))
	{
		Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
		goto err;
	}

	sprintf (mapDevice, TC_MAP_DEV "%d", devNo);

	if (Verbose >= 1)
		printf ("Mapped %s as %s\n", volumePath, mapDevice);

	// Mount
	if (mountPoint)
	{
		char fstype[64], opts[128];

		strcpy (fstype, "-t");
		if (Filesystem)
			strncat (fstype, Filesystem, sizeof (fstype) - 3);
		else
			strcat (fstype, "auto");

		strcpy (opts, ReadOnly ? "-oro" : "-orw");
		if (MountOpts)
		{
			strcat (opts, ",");
			strncat (opts, MountOpts, sizeof (opts) - 6);
		}

		if (UserMount)
		{
			// Set default uid and gid
			char s[64];
			sprintf (s, ",uid=%d,gid=%d", RealUserId, RealGroupId);
			strcat (opts, s);
		}

		if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
		{
			error ("Mount failed\n");
			loopDevNo = -1;
			goto err;
		}

		if (Verbose >= 1)
			printf ("Mounted %s at %s\n", mapDevice, mountPoint);
	}

	crypto_close (ci);

	return TRUE;

err:
	if (ci)
		crypto_close (ci);

	if (loopDevNo != -1)
		DeleteLoopDevice (loopDevNo);

	UnloadKernelModule (TRUE);

	return FALSE;
}


int RandGetBytesAvailable ()
{
	int n = -1;
	FILE *f = fopen ("/proc/sys/kernel/random/entropy_avail", "r");
	
	if (f == NULL)
		return -1;

	if (fscanf (f, "%d", &n) == 1)
		n /= 8;

	fclose (f);
	return n;
}


void RandBytesFillRequired (int randReq)
{
	int n;

	if (RandGetBytesAvailable () < randReq)
	{
		printf ("There is not enough entropy available in the kernel random pool. Please move\n"
			"the mouse randomly and/or press random keys. Both the mouse and keyboard must\n"
			"be physically connected to the computer where TrueCrypt is running. Disk\n"
			"activity (read/write) can also be used to fill the kernel random pool.\n\n");

		while ((n = RandGetBytesAvailable()) < randReq)
		{
			if (n < 0)
			{
				printf ("WARNING: Number of random bytes available could not be determined.\n"
					"If the volume creation does not start, try moving the mouse or pressing keys\n"
					"to increase the random pool entropy.\n");
				break;
			}

			printf ("\rRandom bytes available: %d%%", n * 100 / (randReq));
			fflush (stdout);
			usleep (200 * 1000);
		}

		if (n > 0)
			printf ("\rRandom bytes available: 100%%\n\n");
	}
}


BOOL RandpeekBytes (unsigned char *buf , int len)
{
	int f = open ("/dev/urandom", 0);

	if (f == -1)
	{
		perror ("Cannot open /dev/urandom");
		return FALSE;
	}

	if (read (f, buf, len) != len)
	{
		perror ("Read from /dev/urandom failed");
		return FALSE;
	}

	close (f);
	return TRUE;
}


BOOL RandgetBytes (unsigned char *buf , int len, BOOL forceSlowPoll)
{
	char m[128];
	int f = open ("/dev/random", 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -