📄 pgpkeylib.c
字号:
}
/* Make sure trust and validity info is correct. This also
ensures the keyrings are rewritten if ringFileOpen set
the RINGFILEF_TRUSTCHANGED or RINGFILEF_DIRTY flags. */
if ((errorVal = pgpCommitKeyRingChanges(set)) != PGPERR_OK)
goto error;
errorVal = PGPERR_OK;
error:
if (dbsec != NULL)
pgpFreeKeyDB(dbsec);
if (dbpub != NULL)
pgpFreeKeyDB(dbpub);
if (dbunion != NULL)
pgpFreeKeyDB(dbunion);
if (set != NULL && errorVal != PGPERR_OK)
{
pgpFreeKeySet(set);
set = NULL;
}
if (errorPtr != NULL)
{
pgpAssertAddrValid(errorPtr, PGPError);
*errorPtr = errorVal;
}
return set;
}
/*
* Open a single specified keyring file for user, return keyset for it.
* If isMutable is false, keyrings are read only.
* If isTrusted is false, trust packets are ignored.
* If <errorPtr> is non-NULL, it is filled with an appropriate error code.
*/
PGPKeySet *
pgpOpenKeyRing(Boolean isMutable, Boolean isPrivate, Boolean isTrusted,
PGPFileRef *fileRef, PGPError *errorPtr)
{
PGPKeyDB *db = NULL;
PGPKeySet *set = NULL;
PGPError errorVal = PGPERR_OK;
pgpAssertMsg(pgpLibSetup > 0,
"pgpOpenKeyRing: pgpLibInit hasn't been called");
/* Create a key databases for this file. Don't bother with keypool.
Private keyring is not trusted (no trust packets) */
if ((db = pgpCreateFileKeyDB(fileRef, isTrusted, isPrivate, isMutable,
pgpRingPool, &errorVal)) == NULL)
goto error;
if ((errorVal = pgpBuildKeyPool(db, 0)) != PGPERR_OK)
goto error;
if ((set = pgpKeyDBRootSet(db)) == NULL)
{
errorVal = PGPERR_NOMEM; /* XXX Improve error */
goto error;
}
/* Make sure trust and validity info is correct. This also
ensures the keyrings are rewritten if ringFileOpen set
the RINGFILEF_TRUSTCHANGED or RINGFILEF_DIRTY flags. */
if ((errorVal = pgpCommitKeyRingChanges(set)) != PGPERR_OK)
goto error;
errorVal = PGPERR_OK;
error:
if (db != NULL)
pgpFreeKeyDB(db);
if (set != NULL && errorVal != PGPERR_OK)
{
pgpFreeKeySet(set);
set = NULL;
}
if (errorPtr != NULL)
{
pgpAssertAddrValid(errorPtr, PGPError);
*errorPtr = errorVal;
}
return set;
}
/* Add keys to a keyset from a dynamically allocated binary key buffer */
static PGPKeySet *
pgpImportKeyX (byte *buffer, size_t length)
{
PGPKeyDB *kdb;
PGPKeySet *set;
PGPError error;
/* Create a file type KeyDB from the buffer */
kdb = pgpCreateMemFileKeyDB (buffer, length, pgpRingPool, &error);
if (!kdb) {
pgpMemFree (buffer);
return NULL;
}
error = pgpBuildKeyPool (kdb, 0);
if (error) {
pgpFreeKeyDB (kdb);
return NULL;
}
set = pgpKeyDBRootSet (kdb);
pgpFreeKeyDB (kdb);
return set;
}
/* Open the specified keyfile and add to the existing KeySet */
PGPKeySet *
pgpImportKeyFile (PGPFileRef *fileRef)
{
byte *filebuf;
size_t filebuflen;
PGPError err;
err = pgpDearmorKeyFile (pgpEnv, fileRef, &filebuf, &filebuflen);
if (err)
return NULL;
return pgpImportKeyX (filebuf, filebuflen);
}
/* Add the data from the specified memory buffer to the existing KeySet */
PGPKeySet *
pgpImportKeyBuffer (byte *buffer, size_t length)
{
byte *filebuf;
size_t filebuflen;
PGPError err;
err = pgpDearmorKeyBuffer (pgpEnv, buffer, length, &filebuf, &filebuflen);
if (err)
return NULL;
return pgpImportKeyX (filebuf, filebuflen);
}
/*
* Filter function for extraction. Remove any secret objects.
* If addmrks is true, also add any message recovery key objects to
* the set. This will cause MRK's to be extracted with the keys
* that use them.
* XXX THIS DOES NOT YET WORK. There is no RingSet available in which
* to look for MRK's. The export functions typically are called with
* just a memory RingSet. We need to add versions which take an extra
* PGPKeySet to flag that MRK's should be looked for there.
*/
static RingSet *
filterPubRingSet (RingSet *rset, PGPKeySet *keys, Boolean addmrks)
{
RingSet *rsetnew; /* Set of recipients */
RingSet *rkeyset; /* Set of message recovery keys */
RingIterator *riter; /* Iterator over adding sets */
int level;
if (!rset)
return NULL;
rkeyset = NULL;
rsetnew = ringSetCreate (ringSetPool (rset));
if (!rsetnew)
return NULL;
riter = ringIterCreate (rset);
if (!riter) {
ringSetDestroy (rsetnew);
return NULL;
}
/*
* Copy objects in PGPKeySet to rsetnew except secret objects.
* At the same time, accumulate any message recovery keys into
* rkeyset.
*/
while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
RingObject *obj = ringIterCurrentObject (riter, level);
/* Skip secret objects and non-members */
if (ringObjectType (obj) == RINGTYPE_SEC)
continue;
if (!(*keys->isMember)(keys, obj))
continue;
ringSetAddObject (rsetnew, obj);
/* For key objects, look for message recovery keys */
if (addmrks && ringObjectType (obj) == RINGTYPE_KEY) {
RingObject *rkey; /* Recovery key */
unsigned nrkeys; /* Number of recovery keys */
if (ringKeyRecoveryKey (obj, rset, 0, NULL, &nrkeys, NULL)) {
/* Add to special set for recovery keys */
while (nrkeys-- > 0) {
rkey = ringKeyRecoveryKey (obj, rset, nrkeys, NULL,
NULL, NULL);
pgpAssert (rkey);
if (!rkeyset) {
rkeyset = ringSetCreate (ringSetPool(rset));
if (!rkeyset) {
ringIterDestroy (riter);
ringSetDestroy (rsetnew);
return NULL;
}
}
ringSetAddObjectChildren (rkeyset, rset, rkey);
}
}
}
}
ringIterDestroy (riter);
/* Last, merge rkeyset into rsetnew, also stripping secrets */
if (rkeyset) {
ringSetFreeze (rkeyset);
riter = ringIterCreate (rkeyset);
if (!riter) {
ringSetDestroy (rkeyset);
ringSetDestroy (rsetnew);
return NULL;
}
/* Loop over rsetnew iterator, adding non-secret objects */
while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
RingObject *obj = ringIterCurrentObject (riter, level);
if (ringObjectType (obj) == RINGTYPE_SEC)
continue;
ringSetAddObject (rsetnew, obj);
}
ringIterDestroy (riter);
ringSetDestroy (rkeyset);
}
/* Return new set in frozen form */
ringSetFreeze (rsetnew);
return rsetnew;
}
/*
* Extract all keys in the specified KeySet to the specified file. This
* version always ascii armors them.
* Only extracts public portions of keys.
*/
PGPError
pgpExportKeyFile (PGPKeySet *keys, PGPFileRef *fileRef)
{
RingSet *rset,
*rsetpub;
FILE *fp;
PGPError error;
fp = pgpFileRefStdIOOpen(fileRef, (kPGPFileOpenStdWriteFlags
| kPGPFileOpenTextMode),
kPGPFileTypeExportedKeys, &error);
if (!fp)
return error;
rset = pgpKeyDBRingSet (keys->keyDB);
rsetpub = filterPubRingSet (rset, keys, FALSE);
if (!rsetpub) {
pgpStdIOClose (fp);
pgpDeleteFile(fileRef);
return PGPERR_NOMEM;
}
error = (PGPError)pgpWriteArmoredSetFile (fp, rsetpub, pgpEnv);
pgpStdIOClose (fp);
ringSetDestroy (rsetpub);
return error;
}
/*
* Extract all keys in the specified KeySet to the specified memory
* buffer, which is of size *length. Return number of bytes written
* in *length. This version always ascii armors the keys.
* Only extracts public portions of keys.
*/
PGPError
pgpExportKeyBuffer (PGPKeySet *keys, byte *buffer, size_t *length)
{
RingSet *rset,
*rsetpub;
PGPError error;
rset = pgpKeyDBRingSet (keys->keyDB);
rsetpub = filterPubRingSet (rset, keys, FALSE);
if (!rsetpub) {
return PGPERR_NOMEM;
}
error = (PGPError) pgpWriteArmoredSetBuffer (buffer, length, rsetpub,
pgpEnv);
ringSetDestroy (rsetpub);
return error;
}
#if defined(_WIN32)
#define SEMAPHORENAME ("PGPkeysInstSem")
static HANDLE hSem;
/*
* Return TRUE if we have the interlock semaphore, FALSE if someone else
* has it
*/
Boolean
pgpOpenSemaphore ()
{
/* If already been called, return false */
if (hSem)
return FALSE;
/* Create or open a named semaphore */
hSem = CreateSemaphore (NULL, 0, 1, SEMAPHORENAME);
/* If another instance exists, close handle and return false */
if ((hSem != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)) {
CloseHandle(hSem);
hSem = (HANDLE)0;
return FALSE;
}
/* If new semaphore was created, return TRUE. */
return TRUE;
}
/* Clear the semaphore which keeps others from running */
void
pgpCloseSemaphore ()
{
if (!hSem)
return;
CloseHandle (hSem);
hSem = (HANDLE)0;
}
#else
/*
* Return TRUE if we have the interlock semaphore, FALSE if someone else
* has it
*/
Boolean
pgpOpenSemaphore ()
{
return TRUE;
}
/* Release the interlock semaphore */
void
pgpCloseSemaphore ()
{
}
#endif
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -