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

Contents of /trunk/Src/wptImportList.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 200 - (show annotations)
Mon Apr 17 09:12:50 2006 UTC (18 years, 10 months ago) by twoaday
File size: 10958 byte(s)
2006-04-16  Timo Schulz  <ts@g10code.de>
 
        * wptHTTP.cpp (getErrorCode): New.
        (connect): Store winsock error code.
        * wptGPGMEData.cpp (is_armor_header): New.
        * wptGPG.cpp (check_gnupg_engine): Free context.
        (gnupg_backup_keyrings): Do not use global vars.
        * wptGPGUtil.cpp (gpg_export_seckey): Export in ascii format.
         
2006-04-15  Timo Schulz  <ts@g10code.de>
 
        * wptKeyManager.cpp (km_get_key): New.
        (km_key_show_revoc_info): New.
        * wptKeyRevokeDlg.cpp (key_revoke_dlg): Cleanups.
        (on_init_dialog): New.
        * wptKeyManagerDlg.cpp (key_manager_dlg_proc): Factour
        out some common code and use km_get_key() instead.
        * wptKeyEditDlgs.cpp (do_init_keylist): Change second
        param type. Change all callers.
        * wptKeyEdit.cpp (addNotation): New.
        * wptKeyEditCB.cpp (editkey_command_handler): Remove 'step'
        param everywhere. Change all callers.


1 /* wptImportList.cpp
2 * Copyright (C) 2001-2006 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 safe_free (c->uid);
86 safe_free (c);
87 }
88
89
90 /* Decode the %-encoded userid in @pend and store it as the first
91 userid in the key @c. */
92 static void
93 decode_userid (char *pend, import_key_t c)
94 {
95 c->uid = (char*)calloc (1, strlen (pend) + 1);
96 if (!c->uid)
97 BUG (NULL);
98 gpg_decode_c_string (pend, &c->uid, strlen (pend) + 1);
99 c->uid[strlen (c->uid) -3] = '\0';
100 }
101
102
103 /* Parse the output of 'gpg --with-colons <data'. */
104 static void
105 parse_colon_key (char *buf, import_key_t c)
106 {
107 const char * s;
108 char *p, *pend;
109 int field = 0, rectype = 0;
110 enum key_t {
111 KEY_none = 0,
112 KEY_primary = 1,
113 KEY_secondary = 2,
114 };
115
116 if (!buf)
117 return; /* EOF */
118
119 if( !strncmp (buf, "pub", 3) || !strncmp (buf, "sec", 3)) {
120 rectype = KEY_primary;
121 if (*buf == 's')
122 c->secret = 1;
123 }
124 else if (!strncmp (buf, "sub", 3) || !strncmp (buf, "ssb", 3))
125 rectype = KEY_secondary;
126 else if (!strncmp (buf, "uid", 3)) {
127 if (!c->uid) {
128 const char *uid = buf+3;
129 while (uid && *uid == ':')
130 uid++;
131 decode_userid ((char *)uid, c);
132 }
133 return;
134 }
135 else
136 return;
137
138 for (p = buf; p; p = pend) {
139 field++;
140 pend = strchr (p, ':');
141 if (pend)
142 *pend++ = 0;
143
144 switch (field) {
145 case 1:
146 if (rectype != KEY_primary)
147 break;
148 for (s = pend; *s && !isdigit ((unsigned int)*s); s++) {
149 switch (*s) {
150 case 'd': c->disabled = 1;break;
151 case 'e': c->expired = 1; break;
152 case 'r': c->revoked = 1; break;
153 }
154 }
155 break;
156
157 case 2:
158 if (rectype == KEY_primary)
159 c->length = atoi (pend);
160 else if (rectype == KEY_secondary)
161 c->subkey_length = atoi (pend);
162 break;
163
164 case 3:
165 if (rectype == KEY_primary)
166 c->pubkey_algo = (gpgme_pubkey_algo_t)atoi (pend);
167 else if (rectype == KEY_secondary)
168 c->subkey_algo = (gpgme_pubkey_algo_t)atoi (pend);
169 break;
170
171 case 4:
172 if (rectype == KEY_primary) {
173 strncpy (c->keyid, pend, 16);
174 c->keyid[16] = 0;
175 }
176 else if (rectype == KEY_secondary) {
177 strncpy (c->subkey_keyid, pend, 16);
178 c->subkey_keyid[16] = 0;
179 }
180 break;
181
182 case 5:
183 if (rectype == KEY_primary)
184 c->timestamp = strtoul (pend, NULL, 10);
185 else if (rectype == KEY_secondary)
186 c->subkey_timestamp = strtoul (pend, NULL, 10);
187 break;
188
189 case 9:
190 if (rectype == KEY_primary && !c->uid && strlen (pend) > 2) {
191 if (!strchr (pend, '[') && !strchr (pend, ']'))
192 decode_userid (pend, c);
193 }
194 break;
195 }
196 }
197 }
198
199 /* Read the next key from data stream @out. The result is stored in @r_key.
200 Return value: 0 on success. */
201 gpgme_error_t
202 gpg_import_next_key (gpgme_data_t out, char **pending_line, import_key_t *r_key)
203 {
204 import_key_t key;
205 int in_cert, got_block = 0;
206 char buf[384];
207 int n=0;
208
209 if (!r_key)
210 return gpg_error (GPG_ERR_INV_ARG);
211
212 key = (import_key_t) calloc (1, sizeof *key);
213 if (!key)
214 return gpg_error (GPG_ERR_ENOMEM);
215
216 if (*pending_line) {
217 parse_colon_key (*pending_line, key);
218 safe_free (*pending_line);
219 *pending_line = NULL;
220 in_cert = 1;
221 }
222 else
223 in_cert = 0;
224
225 while ((n=gpg_data_readline (out, buf, sizeof buf-1)) > 0) {
226 if (!strncmp (buf, "pub", 3) || !strncmp (buf, "sec", 3)) {
227 if (in_cert) {
228 *pending_line = strdup (buf);
229 goto ready;
230 }
231 in_cert = 1;
232 got_block = 1;
233 parse_colon_key (buf, key);
234 }
235 else if (in_cert) {
236 parse_colon_key (buf, key);
237 got_block = 1;
238 }
239 }
240 ready:
241 *r_key = key;
242 if (got_block && n == 0)
243 return 0;
244 return n == 0? gpg_error (GPG_ERR_EOF) : 0;
245 }
246
247
248 /* Return a humand readable key description of @key. */
249 static char*
250 key_description (import_key_t key)
251 {
252 gpgme_pubkey_algo_t pkalgo;
253 gpgme_pubkey_algo_t subalgo = (gpgme_pubkey_algo_t)0;
254 const char *type, *state;
255 char *p;
256 int n=0;
257
258 pkalgo = key->pubkey_algo;
259 if (key->subkey_algo)
260 subalgo = key->subkey_algo;
261 if (key->revoked)
262 state = _("Revoked" );
263 else if (key->expired)
264 state = _("Expired" );
265 else
266 state = "";
267 if (key->secret)
268 type = _("secret key");
269 else
270 type = _("public key");
271
272 n = strlen (state) + strlen (type) + 2*8 + 8;
273 p = new char[n+1];
274 if (!p)
275 BUG (NULL);
276
277 if (!subalgo)
278 _snprintf (p, 64, "%s %s %s", state,
279 get_key_pubalgo (pkalgo),type);
280 else
281 _snprintf (p, 64, "%s %s/%s %s", state,
282 get_key_pubalgo (pkalgo),
283 get_key_pubalgo (subalgo), type);
284 return p;
285 }
286
287
288 /* Add the key @key to the list view control @lv at position @pos. */
289 static int
290 implist_add_key (listview_ctrl_t lv, int pos, import_key_t key)
291 {
292 char *uid = NULL;
293 char buf[128], * desc;
294 const char *t;
295 u32 tt, tt2=0;
296
297 if (listview_add_item( lv, " " ))
298 return WPTERR_GENERAL;
299 t = key->uid;
300 if (!t || strlen (t) < 5) {
301 t = _("Invalid user ID");
302 listview_add_sub_item (lv, pos, IMPL_COL_UID, t);
303 }
304 else {
305 uid = utf8_to_native (t);
306 if (uid) {
307 listview_add_sub_item (lv, pos, IMPL_COL_UID, uid);
308 safe_free (uid);
309 }
310 }
311
312 tt = key->length;
313 if (key->subkey_length > 0)
314 tt2 = key->subkey_length;
315 if (tt && tt2)
316 _snprintf (buf, sizeof buf - 1, "%d/%d", tt, tt2);
317 else
318 _snprintf (buf, sizeof buf-1, "%d", tt);
319 listview_add_sub_item (lv, pos, IMPL_COL_SIZE, buf);
320
321 t = key->keyid;
322 if (!t || strlen (t) < 8)
323 t = "????????????????";
324 _snprintf (buf, sizeof buf -1, "0x%s", t+8);
325 listview_add_sub_item (lv, pos, IMPL_COL_KEYID, buf);
326
327
328 tt = key->timestamp;
329 t = get_key_created (tt);
330 if( !t )
331 t = "????" "-??" "-??";
332 listview_add_sub_item (lv, pos, IMPL_COL_CREATION, (char *)t);
333
334 desc = key_description (key);
335 if (desc) {
336 listview_add_sub_item (lv, pos, IMPL_COL_KTYPE, desc);
337 free_if_alloc (desc);
338 }
339
340 return 0;
341 }
342
343
344 /* Create a list view for list keys. */
345 int
346 implist_build (listview_ctrl_t *lv, HWND ctrl)
347 {
348 struct listview_ctrl_s *c;
349 struct listview_column_s implist[] = {
350 {0, 190, (char *)_("User ID")},
351 {1, 66, (char *)_("Size")},
352 {2, 80, (char *)_("Key ID")},
353 {3, 72, (char *)_("Creation")},
354 {4, 132, (char *)_("Type")},
355 {0, 0, NULL}
356 };
357 int j, rc = 0;
358
359 rc = listview_new (&c);
360 if (rc)
361 return rc;
362 c->ctrl = ctrl;
363 for (j = 0; implist[j].fieldname != NULL; j++)
364 listview_add_column (c, &implist[j]);
365 listview_set_ext_style (c);
366 *lv = c;
367 return 0;
368 }
369
370
371 static int
372 check_import_data (const char *fname, int *r_revcert)
373 {
374 FILE *f;
375 char buf[512];
376 int n;
377
378 f = fopen (fname, "rb");
379 if (!f)
380 return -1;
381
382 *r_revcert = 0;
383 n = fread (buf, 1, 511, f);
384 if (n > 0) {
385 buf[n] = 0;
386 if (strstr (buf, "A revocation certificate should follow"))
387 *r_revcert = 1;
388 }
389
390 fclose (f);
391 return 0;
392 }
393
394
395 /* Load the list view @lv with the contents of the file @file.
396 @r_revcerts contains the number of revocation certs and
397 @r_seckeys the number of imported secret keys. */
398 int
399 implist_load (listview_ctrl_t lv, const char *file,
400 int *r_revcerts, int *r_seckeys)
401 {
402 gpgme_data_t list;
403 gpgme_error_t err;
404 import_key_t key;
405 int rc = 0, is_tmp=0;
406 char *pending_line = NULL;
407 char fname[300], *out;
408
409 if (!file) {
410 err = gpg_data_new_from_clipboard (&list, 0);
411 if (err) {
412 msg_box (NULL, gpgme_strerror( err ), _("Import"), MB_ERR);
413 return WPTERR_CLIP_OPEN;
414 }
415 get_temp_name (fname, 299, "in_gpg_keys");
416 err = gpg_data_release_and_set_file (list, fname);
417 if (err) {
418 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
419 return WPTERR_FILE_CREAT;
420 }
421 file = fname;
422 is_tmp = 1;
423 }
424
425 if (check_import_data (file, r_revcerts)) {
426 msg_box (NULL, _("It is possible that the ASCII-Armor is damaged\n"
427 "and thus a CRC error occurs."),
428 _("Import"), MB_ERR);
429 if (is_tmp)
430 DeleteFile (file);
431 return WPTERR_GENERAL;
432 }
433
434 err = gpg_import_key_list (file, &out);
435 if (err) {
436 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
437 if (is_tmp)
438 DeleteFile (file);
439 return WPTERR_GENERAL;
440 }
441
442 err = gpgme_data_new_from_mem (&list, out, strlen (out), 1);
443 safe_free (out);
444 if (err) {
445 msg_box (NULL, gpgme_strerror (err), _("Import"), MB_ERR);
446 if (is_tmp)
447 DeleteFile (file);
448 return WPTERR_GENERAL;
449 }
450
451 if (r_seckeys)
452 *r_seckeys = 0;
453 while (!rc) {
454 /* XXX if the key has a direct key signature, the user-id field
455 in the --with-colons mode is empty! */
456 rc = gpg_import_next_key (list, &pending_line, &key);
457 if (!rc)
458 rc = implist_add_key (lv, 0, key);
459 if (key->secret)
460 (*r_seckeys)++;
461 import_key_release (key);
462 }
463
464 gpgme_data_release (list);
465 if (is_tmp)
466 DeleteFile (file);
467 return rc;
468 }
469
470
471 /* Release the list view @lv. */
472 void
473 implist_delete (listview_ctrl_t lv)
474 {
475 if (lv) {
476 listview_release (lv);
477 }
478 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26