Projects STRLCPY neomutt Commits 3c423a45
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    auto.def
    skipped 479 lines
    480 480   if {[is-defined _FILE_OFFSET_BITS]} {
    481 481   define-append CFLAGS -D_FILE_OFFSET_BITS=[get-define _FILE_OFFSET_BITS]
    482 482   }
    483  - 
    484 483   pkgconf true gpgme
    485 484   pkgconf true gpg-error
    486  - 
    487  - # Version might look like this: 1.13.1-unknown, so split on both '.' and '-'
    488  - lassign [split [get-define PKG_GPGME_VERSION] .-] gpgme_maj gpgme_min gpgme_patch
    489  - 
    490  - define GPGME_VERSION_NUMBER [format "0x%02x%02x%02x" $gpgme_maj $gpgme_min $gpgme_patch]
    491 485   define CRYPT_BACKEND_GPGME
    492 486  }
    493 487   
    skipped 734 lines
  • ■ ■ ■ ■ ■
    ncrypt/crypt_gpgme.c
    skipped 29 lines
    30 30   * @page crypt_crypt_gpgme Wrapper for PGP/SMIME calls to GPGME
    31 31   *
    32 32   * Wrapper for PGP/SMIME calls to GPGME
    33  - *
    34  - * Some code is build conditionally according to the version of the GPGME library.
    35  - * This table relates the hex GPGME_VERSION_NUMBER to its age:
    36  - *
    37  - * | Version | Hex | Release Date |
    38  - * | :------ | :------- | :----------- |
    39  - * | 1.8.0 | 0x010800 | 2016-11-16 |
    40  - * | 1.9.0 | 0x010900 | 2017-03-28 |
    41  - * | 1.11.0 | 0x010b00 | 2018-04-18 |
    42 33   */
    43 34   
    44 35  #include "config.h"
    skipped 84 lines
    129 120   */
    130 121  static void redraw_if_needed(gpgme_ctx_t ctx)
    131 122  {
    132  -#if (GPGME_VERSION_NUMBER < 0x010800) // GPGME < 1.8.0
    133  - /* gpgme_get_ctx_flag is not available.
    134  - * In this case, stay on the safe side and always redraw. */
    135  - (void) ctx;
    136  - mutt_need_hard_redraw();
    137  -#else
    138 123   const char *s = gpgme_get_ctx_flag(ctx, "redraw");
    139 124   if (!s /* flag not known */ || *s /* flag true */)
    140 125   {
    141 126   mutt_need_hard_redraw();
    142 127   }
    143  -#endif
    144 128  }
    145 129   
    146  -#if (GPGRT_VERSION_NUMBER >= 0x012100) // libgpg-error >= 1.33
    147  -/**
    148  - * cmp_version_strings - Compare version strings
    149  - * @param a First version string
    150  - * @param b Second version string
    151  - * @param level Level to compare (see below)
    152  - * @retval -1 a precedes b
    153  - * @retval 0 a and b are identical
    154  - * @retval 1 b precedes a
    155  - *
    156  - * `level` may be
    157  - * - 0 reserved
    158  - * - 1 format is "<major><patchlevel>"
    159  - * - 2 format is "<major>.<minor><patchlevel>"
    160  - * - 3 format is "<major>.<minor>.<micro><patchlevel>"
    161  - *
    162  - * To ignore the patchlevel in the comparison add 10 to LEVEL.
    163  - * To get a reverse sorting order use a negative number.
    164  - */
    165  -static int cmp_version_strings(const char *a, const char *b, int level)
    166  -{
    167  - return gpgrt_cmp_version(a, b, level);
    168  -}
    169  -#elif (GPGME_VERSION_NUMBER >= 0x010900) // GPGME >= 1.9.0
    170  - 
    171  -/**
    172  - * parse_version_number - Parse a version string
    173  - * @param[in] s String to parse
    174  - * @param[out] number
    175  - * @retval ptr Remainder of the string
    176  - * @retval NULL Error
    177  - *
    178  - * This function parses the first portion of the version number S and
    179  - * stores it at NUMBER. On success, this function returns a pointer
    180  - * into S starting with the first character, which is not part of the
    181  - * initial number portion; on failure, NULL is returned.
    182  - */
    183  -static const char *parse_version_number(const char *s, int *number)
    184  -{
    185  - int val = 0;
    186  - 
    187  - if ((*s == '0') && isdigit(s[1]))
    188  - return NULL; /* Leading zeros are not allowed. */
    189  - for (; isdigit(s[0]); s++)
    190  - {
    191  - val *= 10;
    192  - val += *s - '0';
    193  - }
    194  - *number = val;
    195  - return (val < 0) ? NULL : s;
    196  -}
    197  - 
    198  -/**
    199  - * parse_version_string - Parse a version string
    200  - * @param s String to parse
    201  - * @param major Version MAJOR.x.x
    202  - * @param minor Version x.MINOR.x
    203  - * @param micro Version x.x.MICRO
    204  - * @retval ptr Patch level string
    205  - * @retval NULL There are fewer parts
    206  - *
    207  - * Break up the complete string-representation of the version number S, which
    208  - * is of the following structure: <major number>.<minor number>.<micro
    209  - * number><patch level>. The major, minor and micro number components will be
    210  - * stored in *MAJOR, *MINOR and *MICRO. If MINOR or MICRO is NULL the version
    211  - * number is assumed to have just 1 or 2 parts respectively.
    212  - *
    213  - * On success, the last component, the patch level, will be returned;
    214  - * in failure, NULL will be returned.
    215  - */
    216  -static const char *parse_version_string(const char *s, int *major, int *minor, int *micro)
    217  -{
    218  - s = parse_version_number(s, major);
    219  - if (!s)
    220  - return NULL;
    221  - if (minor)
    222  - {
    223  - if (*s != '.')
    224  - return NULL;
    225  - s++;
    226  - s = parse_version_number(s, minor);
    227  - if (!s)
    228  - return NULL;
    229  - if (micro)
    230  - {
    231  - if (*s != '.')
    232  - return NULL;
    233  - s++;
    234  - s = parse_version_number(s, micro);
    235  - if (!s)
    236  - return NULL;
    237  - }
    238  - else
    239  - {
    240  - if (*s == '.')
    241  - s++;
    242  - }
    243  - }
    244  - else
    245  - {
    246  - if (*s == '.')
    247  - s++;
    248  - }
    249  - return s; /* patchlevel */
    250  -}
    251  - 
    252  -/**
    253  - * cmp_version_strings - Compare two version strings
    254  - * @param a First version string
    255  - * @param b Second version string
    256  - * @param level Level to compare
    257  - *
    258  - * Substitute for the gpgrt based implementation.
    259  - * See above for a description.
    260  - */
    261  -static int cmp_version_strings(const char *a, const char *b, int level)
    262  -{
    263  - int a_major, a_minor, a_micro;
    264  - int b_major, b_minor, b_micro;
    265  - const char *a_plvl = NULL, *b_plvl = NULL;
    266  - int r;
    267  - int ignore_plvl;
    268  - int positive, negative;
    269  - 
    270  - if (level < 0)
    271  - {
    272  - positive = -1;
    273  - negative = 1;
    274  - level = 0 - level;
    275  - }
    276  - else
    277  - {
    278  - positive = 1;
    279  - negative = -1;
    280  - }
    281  - if ((ignore_plvl = (level > 9)))
    282  - level %= 10;
    283  - 
    284  - a_major = a_minor = a_micro = 0;
    285  - a_plvl = parse_version_string(a, &a_major, (level > 1) ? &a_minor : NULL,
    286  - (level > 2) ? &a_micro : NULL);
    287  - if (!a_plvl)
    288  - a_major = a_minor = a_micro = 0; /* Error. */
    289  - 
    290  - b_major = b_minor = b_micro = 0;
    291  - b_plvl = parse_version_string(b, &b_major, (level > 1) ? &b_minor : NULL,
    292  - (level > 2) ? &b_micro : NULL);
    293  - if (!b_plvl)
    294  - b_major = b_minor = b_micro = 0;
    295  - 
    296  - if (!ignore_plvl)
    297  - {
    298  - if (!a_plvl && !b_plvl)
    299  - return negative; /* Put invalid strings at the end. */
    300  - if (a_plvl && !b_plvl)
    301  - return positive;
    302  - if (!a_plvl && b_plvl)
    303  - return negative;
    304  - }
    305  - 
    306  - if (a_major > b_major)
    307  - return positive;
    308  - if (a_major < b_major)
    309  - return negative;
    310  - 
    311  - if (a_minor > b_minor)
    312  - return positive;
    313  - if (a_minor < b_minor)
    314  - return negative;
    315  - 
    316  - if (a_micro > b_micro)
    317  - return positive;
    318  - if (a_micro < b_micro)
    319  - return negative;
    320  - 
    321  - if (ignore_plvl)
    322  - return 0;
    323  - 
    324  - for (; *a_plvl && *b_plvl; a_plvl++, b_plvl++)
    325  - {
    326  - if ((*a_plvl == '.') && (*b_plvl == '.'))
    327  - {
    328  - r = strcmp(a_plvl, b_plvl);
    329  - if (!r)
    330  - return 0;
    331  - if (r > 0)
    332  - return positive;
    333  - return negative;
    334  - }
    335  - if (*a_plvl == '.')
    336  - return negative; /* B is larger. */
    337  - if (*b_plvl == '.')
    338  - return positive; /* A is larger. */
    339  - if (*a_plvl != *b_plvl)
    340  - break;
    341  - }
    342  - if (*a_plvl == *b_plvl)
    343  - return 0;
    344  - if ((*(signed char *) a_plvl - *(signed char *) b_plvl) > 0)
    345  - return positive;
    346  - return negative;
    347  -}
    348  -#endif
    349  - 
    350 130  /**
    351 131   * crypt_keyid - Find the ID for the key
    352 132   * @param k Key to use
    skipped 278 lines
    631 411   return data;
    632 412  }
    633 413   
    634  -#if (GPGME_VERSION_NUMBER >= 0x010900) // GPGME >= 1.9.0
    635  -/**
    636  - * have_gpg_version - Do we have a sufficient GPG version
    637  - * @param version Minimum version
    638  - * @retval true Minimum version is available
    639  - *
    640  - * Return true if the OpenPGP engine's version is at least VERSION.
    641  - */
    642  -static bool have_gpg_version(const char *version)
    643  -{
    644  - static char *engine_version = NULL;
    645  - 
    646  - if (!engine_version)
    647  - {
    648  - gpgme_ctx_t ctx = NULL;
    649  - gpgme_engine_info_t engineinfo = NULL;
    650  - 
    651  - ctx = create_gpgme_context(false);
    652  - engineinfo = gpgme_ctx_get_engine_info(ctx);
    653  - while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
    654  - engineinfo = engineinfo->next;
    655  - if (engineinfo)
    656  - {
    657  - engine_version = mutt_str_dup(engineinfo->version);
    658  - }
    659  - else
    660  - {
    661  - mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
    662  - engine_version = mutt_str_dup("0.0.0");
    663  - }
    664  - gpgme_release(ctx);
    665  - }
    666  - 
    667  - return cmp_version_strings(engine_version, version, 3) >= 0;
    668  -}
    669  -#endif
    670  - 
    671 414  /**
    672 415   * body_to_data_object - Create GPGME object from the mail body
    673 416   * @param a Body to use
    skipped 191 lines
    865 608   return rv;
    866 609  }
    867 610   
    868  -#if (GPGME_VERSION_NUMBER >= 0x010b00) // GPGME >= 1.11.0
    869 611  /**
    870 612   * create_recipient_string - Create a string of recipients
    871 613   * @param keylist Keys, space-separated
    skipped 26 lines
    898 640   } while (*s != '\0');
    899 641  }
    900 642   
    901  -#else
    902  -/**
    903  - * recipient_set_free - Free a set of recipients
    904  - * @param p_rset Set of GPGME keys
    905  - */
    906  -static void recipient_set_free(gpgme_key_t **p_rset)
    907  -{
    908  - gpgme_key_t *rset = NULL;
    909  - 
    910  - if (!p_rset)
    911  - return;
    912  - 
    913  - rset = *p_rset;
    914  - if (!rset)
    915  - return;
    916  - 
    917  - while (*rset)
    918  - {
    919  - gpgme_key_t k = *rset;
    920  - gpgme_key_unref(k);
    921  - rset++;
    922  - }
    923  - 
    924  - FREE(p_rset);
    925  -}
    926  - 
    927  -/**
    928  - * create_recipient_set - Create a GpgmeRecipientSet from a string of keys
    929  - * @param keylist Keys, space-separated
    930  - * @param use_smime Use SMIME
    931  - * @retval ptr GPGME key set
    932  - */
    933  -static gpgme_key_t *create_recipient_set(const char *keylist, bool use_smime)
    934  -{
    935  - int err;
    936  - const char *s = NULL;
    937  - char buf[100] = { 0 };
    938  - gpgme_key_t *rset = NULL;
    939  - unsigned int rset_n = 0;
    940  - gpgme_key_t key = NULL;
    941  - 
    942  - gpgme_ctx_t context = create_gpgme_context(use_smime);
    943  - s = keylist;
    944  - do
    945  - {
    946  - while (*s == ' ')
    947  - s++;
    948  - int i;
    949  - for (i = 0; *s && *s != ' ' && i < sizeof(buf) - 1;)
    950  - buf[i++] = *s++;
    951  - buf[i] = '\0';
    952  - if (*buf != '\0')
    953  - {
    954  - if ((i > 1) && (buf[i - 1] == '!'))
    955  - {
    956  - /* The user selected to override the validity of that key. */
    957  - buf[i - 1] = '\0';
    958  - 
    959  - err = gpgme_get_key(context, buf, &key, 0);
    960  - if (err == 0)
    961  - key->uids->validity = GPGME_VALIDITY_FULL;
    962  - buf[i - 1] = '!';
    963  - }
    964  - else
    965  - err = gpgme_get_key(context, buf, &key, 0);
    966  - mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
    967  - if (err == 0)
    968  - rset[rset_n++] = key;
    969  - else
    970  - {
    971  - mutt_error(_("error adding recipient '%s': %s"), buf, gpgme_strerror(err));
    972  - rset[rset_n] = NULL;
    973  - recipient_set_free(&rset);
    974  - gpgme_release(context);
    975  - return NULL;
    976  - }
    977  - }
    978  - } while (*s);
    979  - 
    980  - /* NULL terminate. */
    981  - mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
    982  - rset[rset_n++] = NULL;
    983  - 
    984  - gpgme_release(context);
    985  - 
    986  - return rset;
    987  -}
    988  -#endif
    989  - 
    990 643  /**
    991 644   * set_signer_from_address - Try to set the context's signer from the address
    992 645   * @param ctx GPGME handle
    skipped 132 lines
    1125 778   gpgme_data_t ciphertext = NULL;
    1126 779   char *outfile = NULL;
    1127 780   
    1128  -#if (GPGME_VERSION_NUMBER >= 0x010b00) // GPGME >= 1.11.0
    1129 781   struct Buffer *recpstring = mutt_buffer_pool_get();
    1130 782   create_recipient_string(keylist, recpstring, use_smime);
    1131 783   if (mutt_buffer_is_empty(recpstring))
    skipped 1 lines
    1133 785   mutt_buffer_pool_release(&recpstring);
    1134 786   return NULL;
    1135 787   }
    1136  -#else
    1137  - gpgme_key_t *rset = create_recipient_set(keylist, use_smime);
    1138  - if (!rset)
    1139  - return NULL;
    1140  -#endif
    1141 788   
    1142 789   ctx = create_gpgme_context(use_smime);
    1143 790   if (!use_smime)
    skipped 14 lines
    1158 805   goto cleanup;
    1159 806   }
    1160 807   
    1161  -#if (GPGME_VERSION_NUMBER >= 0x010b00) // GPGME >= 1.11.0
    1162 808   err = gpgme_op_encrypt_sign_ext(ctx, NULL, mutt_buffer_string(recpstring),
    1163 809   GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
    1164  -#else
    1165  - err = gpgme_op_encrypt_sign(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
    1166  -#endif
    1167 810   }
    1168 811   else
    1169 812   {
    1170  -#if (GPGME_VERSION_NUMBER >= 0x010b00) // GPGME >= 1.11.0
    1171 813   err = gpgme_op_encrypt_ext(ctx, NULL, mutt_buffer_string(recpstring),
    1172 814   GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
    1173  -#else
    1174  - err = gpgme_op_encrypt(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
    1175  -#endif
    1176 815   }
    1177 816   
    1178 817   redraw_if_needed(ctx);
    skipped 6 lines
    1185 824   outfile = data_object_to_tempfile(ciphertext, NULL);
    1186 825   
    1187 826  cleanup:
    1188  -#if (GPGME_VERSION_NUMBER >= 0x010b00) // GPGME >= 1.11.0
    1189 827   mutt_buffer_pool_release(&recpstring);
    1190  -#else
    1191  - recipient_set_free(&rset);
    1192  -#endif
    1193 828   gpgme_release(ctx);
    1194 829   gpgme_data_release(ciphertext);
    1195 830   return outfile;
    skipped 1228 lines
    2424 2059   */
    2425 2060  static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
    2426 2061  {
    2427  - /* Before GPGME 1.9.0 and gpg 2.1.14 there was no side-effect free
    2428  - * way to view key data in GPGME, so we import the key into a
    2429  - * temporary keyring if we detect an older system. */
    2430  - bool legacy_api;
    2431  - struct Buffer *tmpdir = NULL;
    2432 2062   gpgme_ctx_t tmpctx = NULL;
    2433 2063   gpgme_error_t err;
    2434  - gpgme_engine_info_t engineinfo = NULL;
    2435 2064   gpgme_key_t key = NULL;
    2436 2065   gpgme_user_id_t uid = NULL;
    2437 2066   gpgme_subkey_t subkey = NULL;
    skipped 4 lines
    2442 2071   int rc = -1;
    2443 2072   time_t tt;
    2444 2073   
    2445  -#if (GPGME_VERSION_NUMBER >= 0x010900) // GPGME >= 1.9.0
    2446  - legacy_api = !have_gpg_version("2.1.14");
    2447  -#else
    2448  - legacy_api = true;
    2449  -#endif
    2450  - 
    2451  - tmpctx = create_gpgme_context(false);
    2452  - 
    2453  - if (legacy_api)
    2454  - {
    2455  - tmpdir = mutt_buffer_pool_get();
    2456  - const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
    2457  - mutt_buffer_printf(tmpdir, "%s/neomutt-gpgme-XXXXXX", NONULL(c_tmpdir));
    2458  - if (!mkdtemp(tmpdir->data))
    2459  - {
    2460  - mutt_debug(LL_DEBUG1, "Error creating temporary GPGME home\n");
    2461  - goto err_ctx;
    2462  - }
    2463  - 
    2464  - engineinfo = gpgme_ctx_get_engine_info(tmpctx);
    2465  - while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
    2466  - engineinfo = engineinfo->next;
    2467  - if (!engineinfo)
    2468  - {
    2469  - mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
    2470  - goto err_tmpdir;
    2471  - }
    2472  - 
    2473  - err = gpgme_ctx_set_engine_info(tmpctx, GPGME_PROTOCOL_OpenPGP, engineinfo->file_name,
    2474  - mutt_buffer_string(tmpdir));
    2475  - if (err != GPG_ERR_NO_ERROR)
    2476  - {
    2477  - mutt_debug(LL_DEBUG1, "Error setting GPGME context home\n");
    2478  - goto err_tmpdir;
    2479  - }
    2480  - }
    2481  - 
    2482 2074   *fp = mutt_file_mkstemp();
    2483 2075   if (!*fp)
    2484 2076   {
    2485 2077   mutt_perror(_("Can't create temporary file"));
    2486  - goto err_tmpdir;
     2078 + return -1;
    2487 2079   }
    2488 2080   
    2489  -#if (GPGME_VERSION_NUMBER >= 0x010900) // GPGME >= 1.9.0
    2490  - if (!legacy_api)
    2491  - err = gpgme_op_keylist_from_data_start(tmpctx, keydata, 0);
    2492  - else
    2493  -#endif
    2494  - {
    2495  - err = gpgme_op_keylist_start(tmpctx, NULL, 0);
    2496  - }
     2081 + tmpctx = create_gpgme_context(false);
     2082 + 
     2083 + err = gpgme_op_keylist_from_data_start(tmpctx, keydata, 0);
    2497 2084   while (err == 0)
    2498 2085   {
    2499 2086   err = gpgme_op_keylist_next(tmpctx, &key);
    skipped 37 lines
    2537 2124  err_fp:
    2538 2125   if (rc)
    2539 2126   mutt_file_fclose(fp);
    2540  -err_tmpdir:
    2541  - if (legacy_api)
    2542  - mutt_file_rmtree(mutt_buffer_string(tmpdir));
    2543  -err_ctx:
     2127 + 
    2544 2128   gpgme_release(tmpctx);
    2545  - 
    2546  - mutt_buffer_pool_release(&tmpdir);
    2547 2129   
    2548 2130   return rc;
    2549 2131  }
    skipped 1897 lines
  • ■ ■ ■ ■ ■ ■
    ncrypt/gpgme_functions.c
    skipped 761 lines
    762 762   mutt_clear_error();
    763 763   return FR_NO_ACTION;
    764 764   }
    765  - 
    766  - /* A '!' is appended to a key in find_keys() when forced_valid is
    767  - * set. Prior to GPGME 1.11.0, encrypt_gpgme_object() called
    768  - * create_recipient_set() which interpreted the '!' to mean set
    769  - * GPGME_VALIDITY_FULL for the key.
    770  - *
    771  - * Starting in GPGME 1.11.0, we now use a '\n' delimited recipient
    772  - * string, which is passed directly to the gpgme_op_encrypt_ext()
    773  - * function. This allows to use the original meaning of '!' to
    774  - * force a subkey use. */
    775  -#if (GPGME_VERSION_NUMBER < 0x010b00) // GPGME < 1.11.0
    776  - if (gd->forced_valid)
    777  - *gd->forced_valid = true;
    778  -#endif
    779 765   }
    780 766   
    781 767   gd->key = crypt_copy_key(cur_key);
    skipped 76 lines
Please wait...
Page is in error, reload to recover