slightly reworking initial PGP key import in case of GnuPG

doc_update_sequoia
Volker Birk 5 years ago
parent c3fe358aec
commit 6d76b00af0

@ -53,7 +53,6 @@ PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first)
cryptotech[PEP_crypt_OpenPGP].key_created = pgp_key_created;
cryptotech[PEP_crypt_OpenPGP].contains_priv_key = pgp_contains_priv_key;
cryptotech[PEP_crypt_OpenPGP].find_private_keys = pgp_find_private_keys;
cryptotech[PEP_crypt_OpenPGP].import_trusted_own_keys = pgp_import_ultimately_trusted_keypairs;
#ifdef PGP_BINARY_PATH
cryptotech[PEP_crypt_OpenPGP].binary_path = PGP_BINARY_PATH;
#endif

@ -89,10 +89,6 @@ typedef PEP_STATUS (*find_private_keys_t)(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
);
typedef PEP_STATUS(*import_trusted_own_keys_t)(
PEP_SESSION session
);
typedef struct _PEP_cryptotech_t {
uint8_t id;
// the following are default values; comm_type may vary with key length or b0rken crypto
@ -118,7 +114,6 @@ typedef struct _PEP_cryptotech_t {
binary_path_t binary_path;
contains_priv_key_t contains_priv_key;
find_private_keys_t find_private_keys;
import_trusted_own_keys_t import_trusted_own_keys;
} PEP_cryptotech_t;
extern PEP_cryptotech_t cryptotech[PEP_crypt__count];

@ -1749,3 +1749,96 @@ PEP_STATUS is_mistrusted_key(PEP_SESSION session, const char* fpr,
sqlite3_reset(session->is_mistrusted_key);
return status;
}
#ifdef USE_GPG
PEP_STATUS pgp_find_trusted_private_keys(
PEP_SESSION session, stringlist_t **keylist
);
enum _pgp_thing {
_pgp_none = 0,
_pgp_fpr,
_pgp_email,
_pgp_name
};
static enum _pgp_thing _pgp_thing_next(enum _pgp_thing thing)
{
switch (thing) {
case _pgp_fpr:
return _pgp_email;
case _pgp_email:
return _pgp_name;
case _pgp_name:
return _pgp_fpr;
default:
return _pgp_fpr;
}
}
PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) {
assert(session);
if (!session)
return PEP_ILLEGAL_VALUE;
stringlist_t* priv_keylist = NULL;
PEP_STATUS status = PEP_STATUS_OK;
// 1. get keys
status = pgp_find_trusted_private_keys(session, &priv_keylist);
if (status)
return status;
pEp_identity *identity = NULL;
stringlist_t *_sl;
char *fpr;
enum _pgp_thing thing = _pgp_none;
for (_sl = priv_keylist; _sl && _sl->value; _sl = _sl->next) {
thing = _pgp_thing_next(thing);
switch (thing) {
case _pgp_fpr:
identity = new_identity(NULL, NULL, PEP_OWN_USERID, NULL);
if (!identity)
status = PEP_OUT_OF_MEMORY;
identity->me = true;
fpr = strdup(_sl->value);
assert(fpr);
if (!fpr) {
status = PEP_OUT_OF_MEMORY;
free_identity(identity);
}
break;
case _pgp_email:
assert(identity);
identity->address = strdup(_sl->value);
assert(identity->address);
if (!identity->address) {
status = PEP_OUT_OF_MEMORY;
free_identity(identity);
}
break;
case _pgp_name:
assert(identity);
identity->username = strdup(_sl->value);
assert(identity->username);
if (!identity->username)
status = PEP_OUT_OF_MEMORY;
else
status = set_own_key(session, identity, fpr);
free_identity(identity);
identity = NULL;
break;
default:
assert(0);
free_identity(identity);
status = PEP_UNKNOWN_ERROR;
}
if (status)
break;
}
free_stringlist(priv_keylist);
return status;
}
#endif // USE_GPG

@ -486,6 +486,10 @@ void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){
fprintf(stderr, "(%d) %s\n", iErrCode, zMsg);
}
#ifdef USE_GPG
PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session);
#endif // USE_GPG
DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
{
PEP_STATUS status = PEP_STATUS_OK;
@ -1294,6 +1298,7 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
if (very_first)
{
#ifdef USE_GPG
// On first run, all private keys already present in PGP keyring
// are taken as own in order to seamlessly integrate with
// pre-existing GPG setup.
@ -1306,7 +1311,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
// private keys have an 'unknown' trust designation in PGP).
// We don't really worry about the status here.
status = import_trusted_own_keys(_session);
status = pgp_import_ultimately_trusted_keypairs(_session);
#endif // USE_GPG
}
// sync_session set to own session by default
@ -3825,14 +3831,6 @@ PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
keylist);
}
PEP_STATUS import_trusted_own_keys(PEP_SESSION session) {
assert(session);
if (!session)
return PEP_ILLEGAL_VALUE;
return session->cryptotech[PEP_crypt_OpenPGP].import_trusted_own_keys(session);
}
DYNAMIC_API const char* get_engine_version() {
return PEP_ENGINE_VERSION;
}

@ -1248,8 +1248,6 @@ PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
PEP_STATUS refresh_userid_default_key(PEP_SESSION session, const char* user_id);
PEP_STATUS import_trusted_own_keys(PEP_SESSION session);
// This ONLY sets the *user* flag, and creates a shell identity if necessary.
PEP_STATUS set_as_pep_user(PEP_SESSION session, pEp_identity* user);

@ -1939,80 +1939,95 @@ PEP_STATUS pgp_find_private_keys(
return _pgp_search_keys(session, pattern, keylist, 1);
}
PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) {
assert(session);
if (!session)
// this function is delivering a list of triples with fpr, email, name of all
// ultimatedly trusted private keys
PEP_STATUS pgp_find_trusted_private_keys(
PEP_SESSION session, stringlist_t **keylist
)
{
assert(session && keylist);
if (!session || !keylist)
return PEP_ILLEGAL_VALUE;
stringlist_t* priv_keylist = NULL;
*keylist = NULL;
gpgme_key_t key;
gpgme_error_t gpgme_error;
PEP_STATUS status = PEP_STATUS_OK;
PEP_STATUS first_fail = PEP_STATUS_OK;
// 1. get keys
first_fail = pgp_find_private_keys(session, NULL, &priv_keylist);
stringlist_t *private_keylist = NULL;
PEP_STATUS status = pgp_find_private_keys(session, NULL, &private_keylist);
if (status)
return status;
if (!private_keylist || !private_keylist->value)
return status;
bool has_already_failed = (first_fail != PEP_STATUS_OK);
stringlist_t *result_list = new_stringlist(NULL);
if (!result_list)
return PEP_OUT_OF_MEMORY;
stringlist_t *_result_list = result_list;
if (!has_already_failed) {
stringlist_t* keylist_curr;
// 2. for each key
for (keylist_curr = priv_keylist; keylist_curr; keylist_curr = keylist_curr->next) {
// a. get key data
if (!keylist_curr->value)
continue;
gpgme_error = gpg.gpgme_get_key(session->ctx, keylist_curr->value, &key, 1);
gpgme_error = _GPGERR(gpgme_error);
assert(gpgme_error != GPG_ERR_ENOMEM);
switch (gpgme_error) {
case GPG_ERR_NO_ERROR:
break;
case GPG_ERR_EOF:
first_fail = (has_already_failed ? first_fail : PEP_KEY_NOT_FOUND);
break;
case GPG_ERR_INV_VALUE:
first_fail = (has_already_failed ? first_fail : PEP_ILLEGAL_VALUE);
break;
case GPG_ERR_AMBIGUOUS_NAME:
first_fail = (has_already_failed ? first_fail : PEP_KEY_HAS_AMBIG_NAME);
break;
case GPG_ERR_ENOMEM:
first_fail = (has_already_failed ? first_fail : PEP_OUT_OF_MEMORY);
break;
default:
assert(0);
first_fail = (has_already_failed ? first_fail : PEP_UNKNOWN_ERROR);
stringlist_t *keylist_curr;
for (keylist_curr = private_keylist; keylist_curr && keylist_curr->value; keylist_curr = keylist_curr->next) {
// a. get key data
gpgme_error = gpg.gpgme_get_key(session->ctx, keylist_curr->value, &key, 1);
gpgme_error = _GPGERR(gpgme_error);
assert(gpgme_error != GPG_ERR_ENOMEM);
switch (gpgme_error) {
case GPG_ERR_NO_ERROR:
break;
case GPG_ERR_EOF:
status = PEP_KEY_NOT_FOUND;
break;
case GPG_ERR_INV_VALUE:
status = PEP_ILLEGAL_VALUE;
break;
case GPG_ERR_AMBIGUOUS_NAME:
status = PEP_KEY_HAS_AMBIG_NAME;
break;
case GPG_ERR_ENOMEM:
free_stringlist(result_list);
free_stringlist(private_keylist);
return PEP_OUT_OF_MEMORY;
default:
assert(0);
status = PEP_UNKNOWN_ERROR;
}
if (key && gpgme_error == GPG_ERR_NO_ERROR) {
if (key->revoked || key->disabled) {
status = PEP_KEY_UNSUITABLE;
}
if (key && gpgme_error == GPG_ERR_NO_ERROR) {
if (key->revoked || key->disabled)
first_fail = (has_already_failed ? first_fail : PEP_KEY_UNSUITABLE);
else {
if (key->fpr && key->secret && key->can_encrypt && key->can_sign) {
if (key->owner_trust == GPGME_VALIDITY_ULTIMATE &&
key->uids && key->uids->address) {
pEp_identity* new_id = new_identity(key->uids->address,
key->fpr,
PEP_OWN_USERID,
key->uids->name);
if (!new_id)
status = PEP_OUT_OF_MEMORY;
else
status = myself(session, new_id);
first_fail = (has_already_failed ? first_fail : status);
else {
if (key->fpr && key->secret && key->can_encrypt && key->can_sign) {
if (key->owner_trust == GPGME_VALIDITY_ULTIMATE &&
key->uids && key->uids->email && key->uids->name) {
_result_list = stringlist_add(_result_list, key->fpr);
if (!_result_list) {
free_stringlist(result_list);
free_stringlist(private_keylist);
return PEP_OUT_OF_MEMORY;
}
_result_list = stringlist_add(_result_list, key->uids->email);
if (!_result_list) {
free_stringlist(result_list);
free_stringlist(private_keylist);
return PEP_OUT_OF_MEMORY;
}
_result_list = stringlist_add(_result_list, key->uids->name);
if (!_result_list) {
free_stringlist(result_list);
free_stringlist(private_keylist);
return PEP_OUT_OF_MEMORY;
}
}
}
}
has_already_failed = first_fail != PEP_STATUS_OK;
}
}
return first_fail;
free_stringlist(private_keylist);
*keylist = result_list;
return PEP_STATUS_OK;
}
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)

Loading…
Cancel
Save