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

📄 cli.c

📁 truecrypt-4.2a-source-cod 文件虚拟磁盘源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!GetMountList (FALSE))
		return FALSE;

	for (i = 0; MountList[i].DeviceNumber != -1; i++)
		if (strcmp (volumePath, MountList[i].VolumePath) == 0)
			return TRUE;

	return FALSE;
}


static int GetFreeMapDevice ()
{
	FILE *p;
	char cmd[128];
	int n;

	if (!GetMountList (FALSE))
		return -1;

	for (n = 0; n < TC_MAX_MINOR; n++)
	{
		int j = 0;
		while (MountList[j].DeviceNumber != -1)
		{
			if (MountList[j].DeviceNumber == n)
				break;
			j++;
		}

		if (MountList[j].DeviceNumber == -1)
			return n;
	}

	return -1;
}


static BOOL DeleteLoopDevice (int loopDeviceNo)
{
	char dev[32];
	BOOL r;
	int i;

	sprintf (dev, TC_LOOP_DEV "%d", loopDeviceNo);
	if (!IsBlockDevice (dev))
		sprintf (dev, TC_LOOP_DEV "/%d", loopDeviceNo);

	for (i = 0; i < 10; i++)
	{
		r = Execute (TRUE, "losetup", "-d", dev, NULL);
		if (r)
			break;

		usleep (200 * 1000);
	}

	if (r && Verbose > 1)
		printf ("Detached %s\n", dev);

	if (!r)
		error ("Failed to detach %s\n", dev);

	return r;
}


static int AskSelection (int defaultChoice, int min, int max)
{
	int c;
	char s[3];

	while (1)
	{
		printf ("Select [%d]: ", defaultChoice);

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

			puts ("");
			return c;
		}

		puts ("");
		return defaultChoice;
	}
}


static BOOL AskYesNo (char *prompt, BOOL defaultNo)
{
	char s[4];

	do
	{
		printf ("%s [%c/%c]: ", prompt, defaultNo ? 'y' : 'Y', defaultNo ? 'N' : 'n');
		fgets (s, sizeof(s), stdin);

		if (s[0] == 'y' || s[0] == 'Y')
			return TRUE;

		if (s[0] == 'n' || s[0] == 'N')
			return FALSE;

	} while (s[0] != '\n');

	return !defaultNo;
}


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[TC_MAX_PATH];

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

	return volumePath;
}


static BOOL AskKeyFiles (char *prompt, KeyFile **firstKeyFile)
{
	char path[TC_MAX_PATH];
	char lprompt[128];

	snprintf (lprompt, sizeof(lprompt), "%s [none]", prompt); 
	while (AskString (lprompt, path, sizeof (path)) && path[0] != 0)
	{
		KeyFile *kf = malloc (sizeof (KeyFile));
		if (!kf)
		{
			perror ("malloc");
			return FALSE;
		}
		strncpy (kf->FileName, path, sizeof (kf->FileName));
		*firstKeyFile = KeyFileAdd (*firstKeyFile, kf);

		snprintf (lprompt, sizeof(lprompt), "%s [finish]", prompt); 
	}

	return TRUE;
}


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

	memset (&volumeStat, 0, sizeof (volumeStat));
	if ((!UpdateTime || ReadOnly)
		&& IsFile (volumePath) && stat (volumePath, &volumeStat) != 0)
	{
		perror ("Cannot open volume");
		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 hidden volume header");
				if (IsFile (volumePath))
					error ("Please check the filesystem supports files larger than 2GB.\n");
				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)
			{
				char s[128];

				sprintf (s, "Incorrect password %sor not a TrueCrypt volume."
					, (FirstKeyFile || FirstProtVolKeyFile) ? "and/or keyfile(s) " : "");

				if (IsTerminal)
				{
					puts (s);
					continue;
				}
				else
				{
					error ("%s\n", s);
					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[TC_MAX_PATH * 2];
	char *e = escapedString;
	char c;

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

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

		*e++ = c;
	}

	return escapedString;
}


static BOOL MountVolume (char *volumePath, char *mountPoint)
{
	char hostDevice[TC_MAX_PATH];
	char mapDevice[TC_MAX_PATH];
	int loopDevNo = -1;
	PCRYPTO_INFO ci = NULL;
	unsigned long long startSector, totalSectors;
	unsigned long long 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;
		unsigned long long 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 < TC_MAX_MINOR; i++)
		{
			snprintf (hostDevice, sizeof (hostDevice), TC_LOOP_DEV "%d", i);

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

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

		if (i >= TC_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, FALSE))
		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 %llu 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 |= TC_READ_ONLY;
	else if (ProtectHidden)
		flags |= TC_HIDDEN_VOLUME_PROTECTION;

⌨️ 快捷键说明

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