📄 pgpuserio.c
字号:
char pass[256];
int i, err, len;
byte pkalg;
byte const *keyid;
StatusOutput(TRUE, "MESSAGE_IS_ENCRYPTED");
for (esk = esklist; esk; esk = pgpEskNext (esk)) {
switch (pgpEskType (esk)) {
case PGP_ESKTYPE_PASSPHRASE:
if (ui->passcache) {
err = pgpPassCacheTryEsk (ui->passcache,
esk, tryKey, tryarg,
key, keylen);
if (err > 0)
return 0; /* success */
/* Ignore errors, err < 0 */
}
/*XXX Add code to get passphrase in batchmode*/
i = 3;
while (i--) {
len = pgpTtyGetPass(ui->showpass,
pass,
sizeof (pass));
err = pgpEskConvDecrypt (esk, ui->env,
pass, len, key);
*keylen = err;
if (err >= 0)
err = tryKey (tryarg, key, *keylen);
if (!err) {
if (ui->passcache)
pgpPassCacheAdd (ui->passcache,
pass, len);
memset (pass, 0, sizeof (pass));
return 0;
}
memset (pass, 0, sizeof (pass));
InteractionOutput(TRUE,
"PASSPHRASE_INCORRECT");
if (i) {
InteractionOutputString(FALSE, " ");
InteractionOutput(FALSE, "TRY_AGAIN");
}
InteractionOutputString(FALSE, "\n");
}
break;
case PGP_ESKTYPE_PUBKEY:
keyid = pgpEskId8 (esk);
pkalg = pgpEskPKAlg (esk);
#if 0 /*Obsolete - BAT 19970609*/
if (!memcmp (keyid, fixedKeyID, 8))
seckey = fixedKeySec ();
else
#endif
if (ui->ringset) {
ringobj = ringKeyById8 (ui->ringset,
pkalg,
keyid);
if (!ringobj)
break;
seckey = ringSecSecKey (ui->ringset,
ringobj,
PGP_PKUSE_ENCRYPT);
ringObjectRelease (ringobj);
}
else
break;
if (!seckey)
break;
if (! seckey->decrypt) {
/* Can't decrypt with this key */
pgpSecKeyDestroy (seckey);
break;
}
/* XXX need to make sure seckey is unlocked */
err = pgpTtyUnlockSeckey (arg, ringobj, seckey, NULL);
if (err) {
pgpSecKeyDestroy (seckey);
break;
}
err = pgpEskPKdecrypt (esk, ui->env, seckey, key);
*keylen = err;
pgpSecKeyDestroy (seckey);
if (err <= 0)
break;
err = tryKey (tryarg, key, *keylen);
if (!err)
return 0;
break;
default:
ErrorOutput(TRUE,
LEVEL_INFORMATION,
"UNKNOWN_ESK",
pgpEskType(esk));
break;
}
}
/*
* At this point, none of the PgpESKs have been decrypted, so let's
* inform the user that we failed.
*/
InformationOutput(TRUE, "CANNOT_DECRYPT");
for (esk = esklist; esk; esk = pgpEskNext (esk)) {
switch (pgpEskType (esk)) {
case PGP_ESKTYPE_PASSPHRASE:
InformationOutputString(FALSE, " ");
InformationOutput(FALSE, "A_PASSPHRASE");
break;
case PGP_ESKTYPE_PUBKEY:
keyid = pgpEskId8 (esk);
pkalg = pgpEskPKAlg (esk);
if (ui->ringset) {
ringobj = ringKeyById8 (ui->ringset, pkalg,
keyid);
if (ringobj) {
ringKeyPrint(OUTPUT_INFORMATION,
ui->ringset,
ringobj, 1);
ringObjectRelease (ringobj);
} else {
pgpTtyPutKeyID (keyid);
}
} else {
InformationOutputString(FALSE, " ");
InformationOutput(FALSE, "KEY_ID");
pgpTtyPutKeyID (keyid);
}
}
}
InformationOutputString(FALSE, "\n");
return PGPANN_PARSER_EATIT;
}
/* Check if file already exists, and whether it is OK to overwrite it.
If +force, no check is made and any existing file will be overwritten.
If +batchmode (but not +force), the default answer is always do not
overwrite. */
int
pgpTtyCheckOverwrite (struct PgpEnv const *env, char const *name)
{
FILE *fp;
int status = 0;
if (!pgpenvGetInt (env, PGPENV_FORCE, NULL, NULL)) {
fp = fopen (name, "r");
if (fp) {
fclose (fp);
if (pgpenvGetInt (env, PGPENV_BATCHMODE,
NULL, NULL)) {
WarningOutput(TRUE,
LEVEL_INFORMATION,
"USE_FORCE_TO_ALLOW_OVERWRITING");
status = PGPERR_NO_FILE;
}
else {
InteractionOutput(TRUE,
"FORCE_OVERWRITE",
name);
if (!pgpTtyGetBool (0, 1))
status = PGPERR_NO_FILE;
}
}
}
if (status)
ErrorOutput(TRUE,
LEVEL_SEVERE,
"UNABLE_TO_OVERWRITE_FILE",
name);
return status;
}
/*This checks for existance of /dev/random (or whatever is configured in the
*appropriate PGP variable). We place the name of the device we checked in
*in RandomDevice (allocating, first); the caller is responsible for
*deallocation with pgpFree(). Returns TRUE if /dev/random is there, FALSE
*if it is not. RandomDevice may be NULL if you don't care what the device
*is, only if it exists. Note also that this function will alert the user if
*the requested device is world-writable.
*/
static Boolean CheckDevRandom(char **RandomDevice, PgpTtyUI *ui)
{
char *DeviceToUse, *prefDevRandom;
Boolean HasDevRandom = TRUE;
FILE *fDev = NULL;
#ifdef HAVE_SYS_STAT_H
/*This is the preferred method, but it may not be universally portable,
*so I've implemented a less-than-desirable check below using definitely
*available functions.
*/
struct stat stat_buf;
#endif
prefDevRandom = (char *)
pgpenvGetString(ui->env, PGPENV_RANDOMDEVICE, NULL, NULL);
if(!prefDevRandom)
prefDevRandom = (char *) "/dev/random";
if(strcmp(prefDevRandom, "/dev/random") != 0) {
WarningOutput(TRUE,
LEVEL_INFORMATION,
"RANDOM_DEVICE_NOT_DEFAULT",
"/dev/random");
}
if(RandomDevice) {
*RandomDevice = pgpAlloc(sizeof(char) * (strlen(prefDevRandom) + 1));
strcpy(*RandomDevice, prefDevRandom);
}
if(RandomDevice && *RandomDevice) {
DeviceToUse = *RandomDevice;
}
else {
DeviceToUse = (char *) prefDevRandom;
}
#ifdef HAVE_SYS_STAT_H
if(stat(DeviceToUse, &stat_buf) == 0) {
/*Check for world-writable /dev/random and warn the user:*/
if(((stat_buf.st_mode & S_IRWXO) == S_IRWXO) ||
((stat_buf.st_mode & S_IRWXG) == S_IRWXG)) {
WarningOutput(TRUE,
LEVEL_SEVERE,
"RANDOM_DEVICE_WRITABLE",
DeviceToUse);
}
}
else {
HasDevRandom = FALSE;
}
#endif
/*People who don't have sys/stat.h miss out on the check of permissions,
*above. People who do have sys/stat.h still execute this code, to make
*sure we can actually READ the random device. sys/stat.h people who
*have random devices they can't read get a warning.
*
*People who don't have sys/stat.h are just generally in trouble.
*/
if(HasDevRandom) {
if((fDev = fopen(DeviceToUse, "r"))) {
fclose(fDev);
HasDevRandom = TRUE;
}
else {
#if HAVE_SYS_STAT_H
ErrorOutput(TRUE,
LEVEL_INFORMATION,
"RANDOM_DEVICE_UNREADABLE",
DeviceToUse);
#endif
HasDevRandom = FALSE;
}
}
return(HasDevRandom);
}
/* /dev/random did basically what /dev/urandom does now in Linux
*kernels < 1.3.33. My best research to date indicates that the
*modern /dev/random, with no bugs large enough to limit its
*cryptographic utility, cames to be in this kernel version. Note
*that I haven't examined every patch from 1.3.33 - 1.2.0, but
*this is my current information (and I'd love to hear about it
*if I'm incorrect).
*
*Basically, what we want to do is check what Linux version we're
*running (from /proc/version). I'm sure there is some more Linux-
*specific way to do this, but checking /proc/version will work on
*systems that aren't Linux (since the check will just fail).
*
*/
static Boolean
VerifyRandomDevOSVersion(void)
{
FILE *inf;
Boolean VersionIsOK = TRUE;
char VersionBuf[256], *p;
unsigned short major = 0, minor = 0, release = 0;
if((inf = fopen("/proc/version", "r"))) {
fgets(VersionBuf, sizeof(VersionBuf), inf);
/*This string is of the form "Linux version Major.Minor.Release.*/
if(strncasecmp(VersionBuf, "Linux version ", 14) == 0) {
p = VersionBuf;
/*Skip the leading text:*/
while(*p && !isdigit(*p))
++p;
major = atoi(p);
/*If major >= 2, we know we're OK, if it's 0, we know we're not.*/
if(major == 1) {
/*Skip the major number and dot:*/
while(*p && isdigit(*p))
++p;
if(*p) {
++p;
minor = atoi(p);
/*If here, we know it's 1.x.y. If x < 3, we know it's
*bad; if > 3, we know it's good.*/
if(minor == 3) {
/*Ok, it's 1.3.y, so we have to actually find out the
*minor version to see if it's OK.*/
/*Skip the minor number and dot:*/
while(*p && isdigit(*p)) {
++p;
}
if(*p) {
release = atoi(p);
}
}
}
}
if(major <= 1 && minor <= 3 && release <= 32) {
VersionIsOK = FALSE;
}
}
}
return(VersionIsOK);
}
/*This adds count bytes from RandomDevice (usually "/dev/random") to the
*random pool.
*/
static unsigned
pgpDevRandomAccum(int fd, unsigned count)
{
char RandBuf;
unsigned short i = 0;
pgpAssert(count);
pgpAssert(fd >= 0);
for(i = 0; i <= count; ++i) {
RandBuf = read(fd, &RandBuf, count);
pgpRandomAddBytes(&pgpRandomPool, (byte *)&RandBuf, sizeof(RandBuf));
pgpRandPoolAddEntropy(256);
}
return(i);
}
/* Assumes the message string is in printf format */
int
pgpTtyMessage (void *arg, int type, int msg, unsigned numargs, ...)
{
struct PgpTtyUI *ui = (struct PgpTtyUI *)arg;
struct PgpUICbArg const *msgarg;
char const *string, *ptr;
va_list ap;
if (type > ui->verbose)
return 0;
string = pgpmsgString (msg);
va_start (ap, numargs);
while ((ptr = strchr(string, '%')) != NULL) {
/* Print part of string leading up to % */
fwrite (string, 1, ptr-string, ui->fp);
if (*++ptr == '%') {
putc ('%', ui->fp);
string = ptr+1;
continue;
}
pgpAssert (numargs--);
msgarg = va_arg (ap, struct PgpUICbArg const *);
switch (*ptr++) {
case 'd': /* int */
pgpAssert (msgarg->type == PGP_UI_ARG_INT);
fprintf (ui->fp, "%d", msgarg->val.i);
break;
case 'l': /* unsigned long (word32) */
pgpAssert(*ptr == 'u');
ptr++;
pgpAssert (msgarg->type == PGP_UI_ARG_WORD32);
fprintf (ui->fp, "%lu",
(unsigned long)msgarg->val.w32);
break;
case 'u': /* unsigned */
pgpAssert (msgarg->type == PGP_UI_ARG_UNSIGNED);
fprintf (ui->fp, "%u", msgarg->val.u);
break;
case 's': /* string */
pgpAssert (msgarg->type == PGP_UI_ARG_STRING);
fprintf (ui->fp, "%s", msgarg->val.s);
break;
case '.': /* buffer (%.*s) */
pgpAssert (*ptr == '*' && ptr[1] == 's');
ptr += 2;
pgpAssert (msgarg->type == PGP_UI_ARG_BUFFER);
fprintf (ui->fp, "%.*s",
(int)msgarg->val.buf.len,
msgarg->val.buf.buf);
break;
default:
pgpAssert (0);
}
string = ptr;
}
/* Print trailing segment of string */
fputs (string, ui->fp);
putc('\n', ui->fp);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -