/src/neomutt/ncrypt/pgp_functions.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file |
3 | | * Pgp functions |
4 | | * |
5 | | * @authors |
6 | | * Copyright (C) 2022 Richard Russon <rich@flatcap.org> |
7 | | * |
8 | | * @copyright |
9 | | * This program is free software: you can redistribute it and/or modify it under |
10 | | * the terms of the GNU General Public License as published by the Free Software |
11 | | * Foundation, either version 2 of the License, or (at your option) any later |
12 | | * version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
17 | | * details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License along with |
20 | | * this program. If not, see <http://www.gnu.org/licenses/>. |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @page pgp_functions Pgp functions |
25 | | * |
26 | | * Pgp functions |
27 | | */ |
28 | | |
29 | | #include "config.h" |
30 | | #include <stdio.h> |
31 | | #include <unistd.h> |
32 | | #include "mutt/lib.h" |
33 | | #include "config/lib.h" |
34 | | #include "core/lib.h" |
35 | | #include "gui/lib.h" |
36 | | #include "pgp_functions.h" |
37 | | #include "lib.h" |
38 | | #include "menu/lib.h" |
39 | | #include "pager/lib.h" |
40 | | #include "question/lib.h" |
41 | | #include "globals.h" |
42 | | #include "mutt_logging.h" |
43 | | #include "pgp.h" |
44 | | #include "pgpinvoke.h" |
45 | | #include "pgpkey.h" |
46 | | #include "pgplib.h" |
47 | | |
48 | | /** |
49 | | * op_exit - Exit this menu - Implements ::pgp_function_t - @ingroup pgp_function_api |
50 | | */ |
51 | | static int op_exit(struct PgpData *pd, int op) |
52 | 0 | { |
53 | 0 | pd->done = true; |
54 | 0 | return FR_SUCCESS; |
55 | 0 | } |
56 | | |
57 | | /** |
58 | | * op_generic_select_entry - Select the current entry - Implements ::pgp_function_t - @ingroup pgp_function_api |
59 | | */ |
60 | | static int op_generic_select_entry(struct PgpData *pd, int op) |
61 | 0 | { |
62 | | /* XXX make error reporting more verbose */ |
63 | |
|
64 | 0 | const int index = menu_get_index(pd->menu); |
65 | 0 | struct PgpUid *cur_key = pd->key_table[index]; |
66 | 0 | if (OptPgpCheckTrust) |
67 | 0 | { |
68 | 0 | if (!pgp_key_is_valid(cur_key->parent)) |
69 | 0 | { |
70 | 0 | mutt_error(_("This key can't be used: expired/disabled/revoked")); |
71 | 0 | return FR_ERROR; |
72 | 0 | } |
73 | 0 | } |
74 | | |
75 | 0 | if (OptPgpCheckTrust && (!pgp_id_is_valid(cur_key) || !pgp_id_is_strong(cur_key))) |
76 | 0 | { |
77 | 0 | const char *str = ""; |
78 | 0 | char buf2[1024]; |
79 | |
|
80 | 0 | if (cur_key->flags & KEYFLAG_CANTUSE) |
81 | 0 | { |
82 | 0 | str = _("ID is expired/disabled/revoked. Do you really want to use the key?"); |
83 | 0 | } |
84 | 0 | else |
85 | 0 | { |
86 | 0 | switch (cur_key->trust & 0x03) |
87 | 0 | { |
88 | 0 | case 0: |
89 | 0 | str = _("ID has undefined validity. Do you really want to use the key?"); |
90 | 0 | break; |
91 | 0 | case 1: |
92 | 0 | str = _("ID is not valid. Do you really want to use the key?"); |
93 | 0 | break; |
94 | 0 | case 2: |
95 | 0 | str = _("ID is only marginally valid. Do you really want to use the key?"); |
96 | 0 | break; |
97 | 0 | } |
98 | 0 | } |
99 | | |
100 | 0 | snprintf(buf2, sizeof(buf2), "%s", str); |
101 | |
|
102 | 0 | if (query_yesorno(buf2, MUTT_NO) != MUTT_YES) |
103 | 0 | { |
104 | 0 | mutt_clear_error(); |
105 | 0 | return FR_NO_ACTION; |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | 0 | pd->key = cur_key->parent; |
110 | 0 | pd->done = true; |
111 | 0 | return FR_SUCCESS; |
112 | 0 | } |
113 | | |
114 | | /** |
115 | | * op_verify_key - Verify a PGP public key - Implements ::pgp_function_t - @ingroup pgp_function_api |
116 | | */ |
117 | | static int op_verify_key(struct PgpData *pd, int op) |
118 | 0 | { |
119 | 0 | FILE *fp_null = fopen("/dev/null", "w"); |
120 | 0 | if (!fp_null) |
121 | 0 | { |
122 | 0 | mutt_perror(_("Can't open /dev/null")); |
123 | 0 | return FR_ERROR; |
124 | 0 | } |
125 | 0 | struct Buffer *tempfile = NULL; |
126 | 0 | tempfile = buf_pool_get(); |
127 | 0 | buf_mktemp(tempfile); |
128 | 0 | FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "w"); |
129 | 0 | if (!fp_tmp) |
130 | 0 | { |
131 | 0 | mutt_perror(_("Can't create temporary file")); |
132 | 0 | mutt_file_fclose(&fp_null); |
133 | 0 | buf_pool_release(&tempfile); |
134 | 0 | return FR_ERROR; |
135 | 0 | } |
136 | | |
137 | 0 | mutt_message(_("Invoking PGP...")); |
138 | |
|
139 | 0 | const int index = menu_get_index(pd->menu); |
140 | 0 | struct PgpUid *cur_key = pd->key_table[index]; |
141 | 0 | char tmpbuf[256] = { 0 }; |
142 | 0 | snprintf(tmpbuf, sizeof(tmpbuf), "0x%s", |
143 | 0 | pgp_fpr_or_lkeyid(pgp_principal_key(cur_key->parent))); |
144 | |
|
145 | 0 | pid_t pid = pgp_invoke_verify_key(NULL, NULL, NULL, -1, fileno(fp_tmp), |
146 | 0 | fileno(fp_null), tmpbuf); |
147 | 0 | if (pid == -1) |
148 | 0 | { |
149 | 0 | mutt_perror(_("Can't create filter")); |
150 | 0 | unlink(buf_string(tempfile)); |
151 | 0 | mutt_file_fclose(&fp_tmp); |
152 | 0 | mutt_file_fclose(&fp_null); |
153 | 0 | } |
154 | |
|
155 | 0 | filter_wait(pid); |
156 | 0 | mutt_file_fclose(&fp_tmp); |
157 | 0 | mutt_file_fclose(&fp_null); |
158 | 0 | mutt_clear_error(); |
159 | 0 | char title[1024] = { 0 }; |
160 | 0 | snprintf(title, sizeof(title), _("Key ID: 0x%s"), |
161 | 0 | pgp_keyid(pgp_principal_key(cur_key->parent))); |
162 | |
|
163 | 0 | struct PagerData pdata = { 0 }; |
164 | 0 | struct PagerView pview = { &pdata }; |
165 | |
|
166 | 0 | pdata.fname = buf_string(tempfile); |
167 | |
|
168 | 0 | pview.banner = title; |
169 | 0 | pview.flags = MUTT_PAGER_NO_FLAGS; |
170 | 0 | pview.mode = PAGER_MODE_OTHER; |
171 | |
|
172 | 0 | mutt_do_pager(&pview, NULL); |
173 | 0 | buf_pool_release(&tempfile); |
174 | 0 | menu_queue_redraw(pd->menu, MENU_REDRAW_FULL); |
175 | 0 | return FR_SUCCESS; |
176 | 0 | } |
177 | | |
178 | | /** |
179 | | * op_view_id - View the key's user id - Implements ::pgp_function_t - @ingroup pgp_function_api |
180 | | */ |
181 | | static int op_view_id(struct PgpData *pd, int op) |
182 | 0 | { |
183 | 0 | const int index = menu_get_index(pd->menu); |
184 | 0 | struct PgpUid *cur_key = pd->key_table[index]; |
185 | 0 | mutt_message("%s", NONULL(cur_key->addr)); |
186 | 0 | return FR_SUCCESS; |
187 | 0 | } |
188 | | |
189 | | // ----------------------------------------------------------------------------- |
190 | | |
191 | | /** |
192 | | * PgpFunctions - All the NeoMutt functions that the Pgp supports |
193 | | */ |
194 | | static const struct PgpFunction PgpFunctions[] = { |
195 | | // clang-format off |
196 | | { OP_EXIT, op_exit }, |
197 | | { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry }, |
198 | | { OP_VERIFY_KEY, op_verify_key }, |
199 | | { OP_VIEW_ID, op_view_id }, |
200 | | { 0, NULL }, |
201 | | // clang-format on |
202 | | }; |
203 | | |
204 | | /** |
205 | | * pgp_function_dispatcher - Perform a Pgp function - Implements ::function_dispatcher_t - @ingroup dispatcher_api |
206 | | */ |
207 | | int pgp_function_dispatcher(struct MuttWindow *win, int op) |
208 | 0 | { |
209 | 0 | if (!win || !win->wdata) |
210 | 0 | return FR_UNKNOWN; |
211 | | |
212 | 0 | struct MuttWindow *dlg = dialog_find(win); |
213 | 0 | if (!dlg) |
214 | 0 | return FR_ERROR; |
215 | | |
216 | 0 | struct PgpData *pd = dlg->wdata; |
217 | |
|
218 | 0 | int rc = FR_UNKNOWN; |
219 | 0 | for (size_t i = 0; PgpFunctions[i].op != OP_NULL; i++) |
220 | 0 | { |
221 | 0 | const struct PgpFunction *fn = &PgpFunctions[i]; |
222 | 0 | if (fn->op == op) |
223 | 0 | { |
224 | 0 | rc = fn->function(pd, op); |
225 | 0 | break; |
226 | 0 | } |
227 | 0 | } |
228 | |
|
229 | 0 | if (rc == FR_UNKNOWN) // Not our function |
230 | 0 | return rc; |
231 | | |
232 | 0 | const char *result = dispatcher_get_retval_name(rc); |
233 | 0 | mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result)); |
234 | |
|
235 | 0 | return rc; |
236 | 0 | } |