Code Monkey home page Code Monkey logo

Comments (2)

alejandro-colomar avatar alejandro-colomar commented on June 12, 2024 1

I don't see ... that it would require the caller to make a copy

I think we're OK. The jobs of the dialogs is to select a key, but as you've spotted they return differently.

By contrast, in dlg_gpgme(), the user selection causes the key to be copied:

static int op_generic_select_entry(struct GpgmeData *gd, int op)
{
const int index = menu_get_index(gd->menu);
struct CryptKeyInfo *cur_key = gd->key_table[index];
/* FIXME make error reporting more verbose - this should be
* easy because GPGME provides more information */
if (OptPgpCheckTrust)
{
if (!crypt_key_is_valid(cur_key))
{
mutt_error(_("This key can't be used: expired/disabled/revoked"));
return FR_ERROR;
}
}
if (OptPgpCheckTrust && (!crypt_id_is_valid(cur_key) || !crypt_id_is_strong(cur_key)))
{
const char *warn_s = NULL;
char buf2[1024];
if (cur_key->flags & KEYFLAG_CANTUSE)
{
warn_s = _("ID is expired/disabled/revoked. Do you really want to use the key?");
}
else
{
warn_s = "??";
switch (cur_key->validity)
{
case GPGME_VALIDITY_NEVER:
warn_s = _("ID is not valid. Do you really want to use the key?");
break;
case GPGME_VALIDITY_MARGINAL:
warn_s = _("ID is only marginally valid. Do you really want to use the key?");
break;
case GPGME_VALIDITY_FULL:
case GPGME_VALIDITY_ULTIMATE:
break;
case GPGME_VALIDITY_UNKNOWN:
case GPGME_VALIDITY_UNDEFINED:
warn_s = _("ID has undefined validity. Do you really want to use the key?");
break;
}
}
snprintf(buf2, sizeof(buf2), "%s", warn_s);
if (query_yesorno(buf2, MUTT_NO) != MUTT_YES)
{
mutt_clear_error();
return FR_NO_ACTION;
}
}
gd->key = crypt_copy_key(cur_key);
gd->done = true;
return FR_SUCCESS;
}

Ahh, this is what I was looking for but didn't find.

Both methods work and I don't think either leaks. My preference of the two styles is for dlg_smime() -- the dialog selects a key from a list, but nothing else.

Agree.

from neomutt.

flatcap avatar flatcap commented on June 12, 2024

SMIME code, probably a couple of memory leaks:

Entirely possible, the code's seldom been looked at.

I don't see ... that it would require the caller to make a copy

I think we're OK.
The jobs of the dialogs is to select a key, but as you've spotted they return differently.


In smime_get_key_by_addr(), we get all the possible keys:

results = smime_get_candidates(mailbox, only_public_key);

and filter it down into matches, then have one of several paths:

neomutt/ncrypt/smime.c

Lines 647 to 670 in 07e12e7

if (matches)
{
if (oppenc_mode)
{
const bool c_crypt_opportunistic_encrypt_strong_keys =
cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
if (trusted_match)
return_key = smime_copy_key(trusted_match);
else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
return_key = smime_copy_key(valid_match);
else
return_key = NULL;
}
else if (trusted_match && !multi_trusted_matches)
{
return_key = smime_copy_key(trusted_match);
}
else
{
return_key = smime_copy_key(dlg_smime(matches, mailbox));
}
smime_key_free(&matches);
}

In the Dialog path, the user selects a key -- this is one of the keys in matches:

static int op_generic_select_entry(struct SmimeData *sd, int op)
{
const int index = menu_get_index(sd->menu);
struct SmimeKey *cur_key = sd->table[index];
if (cur_key->trust != 't')
{
const char *s = "";
switch (cur_key->trust)
{
case 'e':
case 'i':
case 'r':
s = _("ID is expired/disabled/revoked. Do you really want to use the key?");
break;
case 'u':
s = _("ID has undefined validity. Do you really want to use the key?");
break;
case 'v':
s = _("ID is not trusted. Do you really want to use the key?");
break;
}
char buf[1024] = { 0 };
snprintf(buf, sizeof(buf), "%s", s);
if (query_yesorno(buf, MUTT_NO) != MUTT_YES)
{
mutt_clear_error();
return FR_NO_ACTION;
}
}
sd->key = cur_key;
sd->done = true;
return FR_SUCCESS;
}

which is returned:

return sd.key;

All the paths in smime_get_key_by_addr() now call return_key = smime_copy_key() on the selection and then free matches:

smime_key_free(&matches);

Finally, smime_get_key_by_addr() returns the single selected key:

return return_key;

smime_get_key_by_str() follows the same pattern, but more simply.


It is almost identical to dlg_gpgme(), which doesn't require it.

By contrast, in dlg_gpgme(), the user selection causes the key to be copied:

static int op_generic_select_entry(struct GpgmeData *gd, int op)
{
const int index = menu_get_index(gd->menu);
struct CryptKeyInfo *cur_key = gd->key_table[index];
/* FIXME make error reporting more verbose - this should be
* easy because GPGME provides more information */
if (OptPgpCheckTrust)
{
if (!crypt_key_is_valid(cur_key))
{
mutt_error(_("This key can't be used: expired/disabled/revoked"));
return FR_ERROR;
}
}
if (OptPgpCheckTrust && (!crypt_id_is_valid(cur_key) || !crypt_id_is_strong(cur_key)))
{
const char *warn_s = NULL;
char buf2[1024];
if (cur_key->flags & KEYFLAG_CANTUSE)
{
warn_s = _("ID is expired/disabled/revoked. Do you really want to use the key?");
}
else
{
warn_s = "??";
switch (cur_key->validity)
{
case GPGME_VALIDITY_NEVER:
warn_s = _("ID is not valid. Do you really want to use the key?");
break;
case GPGME_VALIDITY_MARGINAL:
warn_s = _("ID is only marginally valid. Do you really want to use the key?");
break;
case GPGME_VALIDITY_FULL:
case GPGME_VALIDITY_ULTIMATE:
break;
case GPGME_VALIDITY_UNKNOWN:
case GPGME_VALIDITY_UNDEFINED:
warn_s = _("ID has undefined validity. Do you really want to use the key?");
break;
}
}
snprintf(buf2, sizeof(buf2), "%s", warn_s);
if (query_yesorno(buf2, MUTT_NO) != MUTT_YES)
{
mutt_clear_error();
return FR_NO_ACTION;
}
}
gd->key = crypt_copy_key(cur_key);
gd->done = true;
return FR_SUCCESS;
}

then crypt_getkeybyaddr() keeps track of the copied key, frees matches and returns the selected key:

neomutt/ncrypt/crypt_gpgme.c

Lines 3256 to 3266 in 07e12e7

k = dlg_gpgme(matches, a, NULL, app, forced_valid);
}
crypt_key_free(&matches);
}
else
{
k = NULL;
}
return k;

crypt_getkeybystr() works the same way.


Both methods work and I don't think either leaks.
My preference of the two styles is for dlg_smime() -- the dialog selects a key from a list, but nothing else.

Looking through the code, there's room for improvement.
We could use TAILQ or ARRAY, rather than a homegrown List implementation,
but those upgrades might require a lot of changes.

from neomutt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.