/[winpt]/trunk/Src/wptImportList.cpp
ViewVC logotype

Contents of /trunk/Src/wptImportList.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 10978 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

1 /* wptImportList.cpp
2 * Copyright (C) 2001-2005 Timo Schulz
3 * Copyright (C) 2005 g10 Code GmbH
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <sys/types.h>
28 #include <ctype.h>
29
30 #include "wptTypes.h"
31 #include "wptGPG.h"
32 #include "wptCommonCtl.h"
33 #include "wptKeylist.h"
34 #include "wptNLS.h"
35 #include "wptErrors.h"
36 #include "wptUTF8.h"
37 #include "wptW32API.h"
38 #include "wptRegistry.h"
39 #include "openpgp.h"
40
41
42 /* Symbolic column ids */
43 enum impl_col_t {
44 IMPL_COL_UID = 0,
45 IMPL_COL_SIZE = 1,
46 IMPL_COL_KEYID = 2,
47 IMPL_COL_CREATION = 3,
48 IMPL_COL_KTYPE = 4
49 };
50
51 /* context to hold information about a key. */
52 struct import_key_s {
53 /* primary userid */
54 char *uid;
55
56 /* 1 = secret key is available. */
57 int secret;
58
59 /* flags */
60 unsigned int disabled:1;
61 unsigned int expired:1;
62 unsigned int revoked:1;
63
64 /* primary key attributes */
65 char keyid[16+1];
66 gpgme_pubkey_algo_t pubkey_algo;
67 size_t length;
68 time_t timestamp;
69
70 /* secondary key attributes */
71 char subkey_keyid[16+1];
72 gpgme_pubkey_algo_t subkey_algo;
73 size_t subkey_length;
74 time_t subkey_timestamp;
75 };
76 typedef struct import_key_s *import_key_t;
77
78
79 /* Release the key in @c. */
80 static void
81 import_key_release (import_key_t c)
82 {
83 if (!c)
84 return;
85 if (c->uid)
86 free (c->uid);
87 free (c);
88 }
89
90
91 /* Decode the %-encoded userid in @pend and store it as the first
92 userid in the key @c. */
93 static void
94 decode_userid (char *pend, import_key_t c)
95 {
96 c->uid = (char*)calloc (1, strlen (pend) + 1);
97 if (!c->uid)
98 BUG (NULL);
99 gpg_decode_c_string (pend, &c->uid, strlen (pend) + 1);
100 c->uid[strlen (c->uid) -3] = '\0';
101
102 }
103
104
105 /* Parse the output of 'gpg --with-colons <data'. */
106 static void
107 parse_colon_key (char *buf, import_key_t c)
108 {
109 const char * s;
110 char *p, *pend;
111 int field = 0, rectype = 0;
112 enum key_t {
113 KEY_none = 0,
114 KEY_primary = 1,
115 KEY_secondary = 2,
116 };
117
118 if (!buf)
119 return; /* EOF */
120
121 if( !strncmp (buf, "pub", 3) || !strncmp (buf, "sec", 3)) {
122 rectype = KEY_primary;
123 if (*buf == 's')
124 c->secret = 1;
125 }
126 else if (!strncmp (buf, "sub", 3) || !strncmp (buf, "ssb", 3))
127 rectype = KEY_secondary;
128 else if (!strncmp (buf, "uid", 3)) {
129 if (!c->uid) {
130 const char *uid = buf+3;
131 while (uid && *uid == ':')
132 uid++;
133 decode_userid ((char *)uid, c);
134 }
135 return;
136 }
137 else
138 return;
139
140 for (p = buf; p; p = pend) {
141 field++;
142 pend = strchr (p, ':');
143 if (pend)
144 *pend++ = 0;
145
146 switch (field) {
147 case 1:
148 if (rectype != KEY_primary)
149 break;
150 for (s = pend; *s && !isdigit ((unsigned int)*s); s++) {
151 switch (*s) {
152 case 'd': c->disabled = 1;break;
153 case 'e': c->expired = 1; break;
154 case 'r': c->revoked = 1; break;
155 }
156 }
157 break;
158
159 case 2:
160 if (rectype == KEY_primary)
161 c->length = atoi (pend);
162 else if (rectype == KEY_secondary)
163 c->subkey_length = atoi (pend);
164 break;
165
166 case 3:
167 if (rectype == KEY_primary)
168 c->pubkey_algo = (gpgme_pubkey_algo_t)atoi (pend);
169 else if (rectype == KEY_secondary)
170 c->subkey_algo = (gpgme_pubkey_algo_t)atoi (pend);
171 break;
172
173 case 4:
174 if (rectype == KEY_primary) {
175 strncpy (c->keyid, pend, 16);
176 c->keyid[16] = 0;
177 }
178 else if (rectype == KEY_secondary) {
179 strncpy (c->subkey_keyid, pend, 16);
180 c->subkey_keyid[16] = 0;
181 }
182 break;
183
184 case 5:
185 if (rectype == KEY_primary)
186 c->timestamp = strtoul (pend, NULL, 10);
187 else if (rectype == KEY_secondary)
188 c->subkey_timestamp = strtoul (pend, NULL, 10);
189 break;
190
191 case 9:
192 if (rectype == KEY_primary && !c->uid && strlen (pend) > 2) {
193 if (!strchr (pend, '[') && !strchr (pend, ']'))
194 decode_userid (pend, c);
195 }
196 break;
197 }
198 }
199 }
200
201 /* Read the next key from data stream @out. The result is stored in @r_key.
202 Return value: 0 on success. */
203 gpgme_error_t
204 gpg_import_next_key (gpgme_data_t out, char **pending_line, import_key_t *r_key)
205 {
206 import_key_t key;
207 int in_cert, got_block = 0;
208 char buf[384];
209 int n=0;
210
211 if (!r_key)
212 return gpg_error (GPG_ERR_INV_ARG);
213
214 key = (import_key_t) calloc (1, sizeof *key);
215 if (!key)
216 return gpg_error (GPG_ERR_ENOMEM);
217
218 if (*pending_line) {
219 parse_colon_key (*pending_line, key);
220 safe_free (*pending_line);
221 *pending_line = NULL;
222 in_cert = 1;
223 }
224 else
225 in_cert = 0;
226
227 while ((n=gpg_data_readline (out, buf, sizeof buf-1)) > 0) {
228 if (!strncmp (buf, "pub", 3) || !strncmp (buf, "sec", 3)) {
229 if (in_cert) {
230 *pending_line = strdup (buf);
231 goto ready;
232 }
233 in_cert = 1;
234 got_block = 1;
235 parse_colon_key (buf, key);
236 }
237 else if (in_cert) {
238 parse_colon_key (buf, key);
239 got_block = 1;
240 }
241 }
242 ready:
243 *r_key = key;
244 if (got_block && n == 0)
245 return 0;
246 return n == 0? gpg_error (GPG_ERR_EOF) : 0;
247 }
248
249
250 /* Return a humand readable key description of @key. */
251 static char*
252 key_description (import_key_t key)
253 {
254 gpgme_pubkey_algo_t pkalgo;
255 gpgme_pubkey_algo_t subalgo = (gpgme_pubkey_algo_t)0;
256 const char *type, *state;
257 char *p;
258 int n=0;
259
260 pkalgo = key->pubkey_algo;
261 if (key->subkey_algo)
262 subalgo = key->subkey_algo;
263 if (key->revoked)
264 state = _("Revoked" );
265 else if (key->expired)
266 state = _("Expired" );
267 else
268 state = "";
269 if (key->secret)
270 type = _("secret key");
271 else
272 type = _("public key");
273
274 n = strlen (state) + strlen (type) + 2*8 + 8;
275 p = new char[n+1];
276 if (!p)
277 BUG (NULL);
278
279 if (!subalgo)
280 _snprintf (p, 64, "%s %s %s", state,
281 get_key_pubalgo (pkalgo),type);
282 else
283 _snprintf (p, 64, "%s %s/%s %s", state,
284 get_key_pubalgo (pkalgo),
285 get_key_pubalgo (subalgo), type);
286 return p;
287 }
288
289
290 /* Add the key @key to the list view control @lv at position @pos. */
291 static int
292 implist_add_key (listview_ctrl_t lv, int pos, import_key_t key)
293 {
294 char *uid = NULL;
295 char buf[128], * desc;
296 const char *t;
297 u32 tt, tt2=0;
298
299 if (listview_add_item( lv, " " ))
300 return WPTERR_GENERAL;
301 t = key->uid;
302 if (!t || strlen (t) < 5) {
303 t = _("Invalid user ID");
304 listview_add_sub_item (lv, pos, IMPL_COL_UID, t);
305 }
306 else {
307 uid = utf8_to_wincp (t, strlen (t));
308 if (uid) {
309 listview_add_sub_item (lv, pos, IMPL_COL_UID, uid);
310 free (uid);
311 }
312 }
313
314 tt = key->length;
315 if (key->subkey_length > 0)
316 tt2 = key->subkey_length;
317 if (tt && tt2)
318 _snprintf (buf, sizeof buf - 1, "%d/%d", tt, tt2);
319 else
320 _snprintf (buf, sizeof buf-1, "%d", tt);
321 listview_add_sub_item (lv, pos, IMPL_COL_SIZE, buf);
322
323 t = key->keyid;
324 if (!t || strlen (t) < 8)
325 t = "????????????????";
326 _snprintf (buf, sizeof buf -1, "0x%s", t+8);
327 listview_add_sub_item (lv, pos, IMPL_COL_KEYID, buf);
328
329
330 tt = key->timestamp;
331 t = get_key_created (tt);
332 if( !t )
333 t = "????" "-??" "-??";
334 listview_add_sub_item (lv, pos, IMPL_COL_CREATION, (char *)t);
335
336 desc = key_description (key);
337 if (desc) {
338 listview_add_sub_item (lv, pos, IMPL_COL_KTYPE, desc);
339 free_if_alloc (desc);
340 }
341
342 return 0;
343 }
344
345
346 /* Create a list view for list keys. */
347 int
348 implist_build (listview_ctrl_t *lv, HWND ctrl)
349 {
350 struct listview_ctrl_s *c;
351 struct listview_column_s implist[] = {
352 {0, 190, (char *)_("User ID")},
353 {1, 66, (char *)_("Size")},
354 {2, 80, (char *)_("Key ID")},
355 {3, 72, (char *)_("Creation")},
356 {4, 132, (char *)_("Type")},
357 {0, 0, NULL}
358 };
359 int j, rc = 0;
360
361 rc = listview_new (&c);
362 if( rc )
363 return rc;
364 c->ctrl = ctrl;
365 for (j = 0; implist[j].fieldname != NULL; j++)
366 listview_add_column (c, &implist[j]);
367 listview_set_ext_style (c);
368 *lv = c;
369 return 0;
370 }
371
372
373 static int
374 check_import_data (const char *fname, int *r_revcert)
375 {
376 FILE *f;
377 char buf[512];
378 int n;
379
380 f = fopen (fname, "rb");
381 if (!f)
382 return -1;
383
384 *r_revcert = 0;
385 n = fread (buf, 1, 511, f);
386 if (n > 0) {
387 buf[n] = 0;
388 if (strstr (buf, "A revocation certificate should follow"))
389 *r_revcert = 1;
390 }
391
392 fclose (f);
393 return 0;
394 }
395
396
397 /* Load the list view @lv with the contents of the file @file.
398 @r_revcerts contains the number of revocation certs and
399 @r_seckeys the number of imported secret keys. */
400 int
401 implist_load (listview_ctrl_t lv, const char *file,
402 int *r_revcerts, int *r_seckeys)
403 {
404 gpgme_data_t list;
405 gpgme_error_t err;
406 import_key_t key;
407 int rc = 0, is_tmp=0;
408 char *pending_line = NULL;
409 char fname[300], *out;
410
411 if (!file) {
412 err = gpg_data_new_from_clipboard (&list, 0);
413 if (err) {
414 msg_box (NULL, gpgme_strerror( err ), _("Import"), MB_ERR);
415 return WPTERR_CLIP_OPEN;
416 }
417 GetTempPath (299, fname);
418 strcat (fname, "in_gpg_keys");
419 err = gpg_data_release_and_set_file (list, fname);
420 if (err) {
421 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
422 return WPTERR_FILE_CREAT;
423 }
424 file = fname;
425 is_tmp = 1;
426 }
427
428 if (check_import_data (file, r_revcerts)) {
429 msg_box (NULL, _("It is possible that the ASCII-Armor is damaged\n"
430 "and thus a CRC error occurs."), _("Import"), MB_ERR);
431 if (is_tmp)
432 remove (file);
433 return WPTERR_GENERAL;
434 }
435
436 err = gpg_import_key_list (file, &out);
437 if (err) {
438 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
439 if (is_tmp)
440 remove (file);
441 return WPTERR_GENERAL;
442 }
443
444 err = gpgme_data_new_from_mem (&list, out, strlen (out), 1);
445 free (out);
446 if (err) {
447 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
448 if (is_tmp)
449 remove (file);
450 return WPTERR_GENERAL;
451 }
452
453 if (r_seckeys)
454 *r_seckeys = 0;
455 while (!rc) {
456 /* XXX if the key has a direct key signature, the user-id field
457 in the --with-colons mode is empty! */
458 rc = gpg_import_next_key (list, &pending_line, &key);
459 if (!rc)
460 rc = implist_add_key (lv, 0, key);
461 if (key->secret)
462 (*r_seckeys)++;
463 import_key_release (key);
464 }
465
466
467 gpgme_data_release (list);
468 if (is_tmp)
469 remove (file);
470 return rc;
471 }
472
473
474 /* Release the list view @lv. */
475 void
476 implist_delete (listview_ctrl_t lv)
477 {
478 if (lv) {
479 listview_release (lv);
480 }
481 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26