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

Contents of /trunk/Src/wptKeyEdit.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: 17686 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 /* wptKeyEdit.cpp - GPG key edit abstraction
2 * Copyright (C) 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 <time.h>
28
29 #include "gpgme.h"
30 #include "wptCommonCtl.h"
31 #include "wptContext.h"
32 #include "wptKeyEdit.h"
33 #include "wptTypes.h"
34 #include "wptW32API.h"
35 #include "wptGPG.h"
36 #include "wptErrors.h"
37
38
39 /* Parse the colon status information of @line and store
40 the information in @rev.
41 Return value: 0 on success. */
42 static gpgme_error_t
43 rev_key_colon_handler (gpg_desig_rev_t *rev, char *line)
44 {
45 char *p, *pend;
46 gpg_desig_rev_t r, t;
47 int field = 0;
48
49 if (!line || strlen (line) < 3)
50 return gpg_error (GPG_ERR_EOF);
51 if (strncmp (line, "rvk", 3))
52 return 0; /* skip this line. */
53
54 log_debug ("rev_key: line=%s\r\n", line);
55
56 r = (gpg_desig_rev_t)calloc (1, sizeof *r);
57 if (!r)
58 return gpg_error (GPG_ERR_ENOMEM);
59 if (!*rev)
60 *rev = r;
61 else {
62 for (t=*rev; t->next; t=t->next)
63 ;
64 t->next = r;
65 }
66
67 p = strdup (line);
68 if (!p)
69 return gpg_error (GPG_ERR_ENOMEM);
70
71 for (;;) {
72 field++;
73 pend = strsep (&p, ":");
74 if (pend == NULL)
75 break;
76 switch (field) {
77 case 4: r->pubkey_algo = (gpgme_pubkey_algo_t)atol (pend); break;
78 case 10: strncpy (r->fpr, pend, 40); r->fpr[40] = 0; break;
79 }
80 }
81 if (p)
82 free (p);
83 return 0;
84 }
85
86
87 /* Parse the colon data output of edit key from @line and
88 store the information in the @inf context.
89 Return value: 0 on success. */
90 static gpgme_error_t
91 uid_inf_colon_handler (gpg_uid_info_t *inf, char *line)
92 {
93 gpg_uid_info_t i, t;
94 char *p, *pend;
95 int field = 0, len = 0;
96
97 if (!line || strlen (line) < 3 || strncmp (line, "uid", 3))
98 return gpg_error (GPG_ERR_EOF);
99
100 i = (gpg_uid_info_t)calloc (1, sizeof *i);
101 if (!i)
102 return gpg_error (GPG_ERR_ENOMEM);
103 if (!*inf)
104 *inf = i;
105 else {
106 for (t=*inf; t->next; t=t->next)
107 ;
108 t->next = i;
109 }
110
111 p = strdup (line);
112 if (!p)
113 return gpg_error (GPG_ERR_ENOMEM);;
114 for (;;) {
115 field++;
116 pend = strsep (&p, ":");
117 if (pend == NULL)
118 break;
119
120 switch (field) {
121 case 2: /* trust info */
122 break;
123
124 case 10: /* user ID */
125 i->name = (char *)calloc (1, strlen (pend)+1);
126 if (!i->name)
127 return gpg_error (GPG_ERR_ENOMEM);;
128 gpg_decode_c_string (pend, &i->name, strlen (pend)+ 1);
129 if (strchr (pend, '<') != NULL && strchr (pend, '>') != NULL) {
130 int pos = strchr (i->name, '<')- i->name + 1;
131 int end = strchr (i->name, '>') - i->name;
132 i->email = (char*) calloc (1, end-pos+2);
133 if (!i->email)
134 return gpg_error (GPG_ERR_ENOMEM);;
135 memcpy (i->email, i->name+pos, (end-pos));
136 }
137 break;
138
139 case 13: /* preferences */
140 if (strstr (pend, "mdc")) {
141 len = strlen (pend) - 4; /* ,mdc */
142 if (strstr (pend, "no-ks-modify")) {
143 i->flags.no_ks_modify = 1;
144 len -= 13; /* ,no-ks-modify */
145 }
146 i->prefs = (char*)calloc (1, len+1);
147 if (!i->prefs)
148 return gpg_error (GPG_ERR_ENOMEM);
149 memcpy (i->prefs, pend, len);
150 i->prefs[len] = '\0';
151 i->flags.mdc = 1;
152 }
153 else {
154 i->prefs = strdup (pend);
155 if (!i->prefs)
156 return gpg_error (GPG_ERR_ENOMEM);
157 i->flags.mdc = 0;
158 }
159 break;
160
161 case 14: /* index/flags */
162 i->index = atol (pend);
163 if (strchr (pend, 'r'))
164 i->flags.revoked = 1;
165 if (strchr (pend, 'p'))
166 i->flags.primary = 1;
167 break;
168 }
169 }
170 if (p)
171 free (p);
172 return 0;
173 }
174
175
176 /* Release the context in @inf. */
177 void
178 gpg_uid_info_release (gpg_uid_info_t list)
179 {
180 gpg_uid_info_t i;
181
182 while (list) {
183 i = list->next;
184 if (list->name) {
185 if (list->name)
186 free (list->name);
187 list->name = NULL;
188 }
189 if (list->prefs) {
190 if (list->prefs)
191 free (list->prefs);
192 list->prefs = NULL;
193 }
194 free (list);
195 list = i;
196 }
197 }
198
199
200 /* Release the context in @rev. */
201 void
202 gpg_desig_rev_release (gpg_desig_rev_t rev)
203 {
204 gpg_desig_rev_t r;
205
206 while (rev) {
207 r = rev->next;
208 free (rev);
209 rev = r;
210 }
211 }
212
213
214 static gpgme_error_t
215 list2_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
216 {
217 DWORD n;
218 const char *s;
219
220 if (!strcmp (key, "keyedit.prompt")) {
221 s = "quit\n";
222 WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
223 }
224 return 0;
225 }
226
227 /* Dummy handler to get the colon data and then quit. */
228 static gpgme_error_t
229 list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
230 {
231 static int step=0;
232 const char *s="";
233 DWORD n;
234
235 if (!strcmp (key, "keyedit.prompt") && step == 0) {
236 step = 1;
237 s = "list\n";
238 WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
239 }
240 else if (!strcmp (key, "keyedit.prompt") && step == 1) {
241 step = 0;
242 s = "quit\n";
243 WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
244 }
245
246 return 0;
247 }
248
249
250 /* Return all designated revokers for this key. If no revoker
251 was set, @r_rev is NULL.
252 Return value: 0 on success. */
253 gpgme_error_t
254 GpgKeyEdit::getDesignatedRevoker (gpg_desig_rev_t *r_rev)
255 {
256 gpgme_data_t out=NULL;
257 gpg_desig_rev_t rev = NULL;
258 gpgme_error_t err;
259 char buf[256];
260
261 if (!this->key)
262 return gpg_error (GPG_ERR_INV_OBJ);
263
264 err = gpgme_data_new (&out);
265 if (err)
266 goto leave;
267
268 err = gpgme_op_edit (ctx, key, list2_handler, NULL, out);
269 if (err)
270 goto leave;
271
272 gpgme_data_rewind (out);
273 while (gpg_data_readline (out, buf, sizeof (buf)-1) > 0)
274 rev_key_colon_handler (&rev, buf);
275 *r_rev = rev;
276
277 leave:
278 if (out)
279 gpgme_data_release (out);
280 if (err) {
281 gpg_desig_rev_release (rev);
282 *r_rev = NULL;
283 }
284 return err;
285 }
286
287 /* Retrieve all user ID information of the key set via setKey
288 in @r_inf. The result also contains the user ID number which
289 is needed to securely delete the user-ID. */
290 gpgme_error_t
291 GpgKeyEdit::getUseridInfo (gpg_uid_info_t *r_uinf)
292 {
293 gpgme_data_t out = NULL;
294 gpgme_error_t err;
295 gpg_uid_info_t inf = NULL;
296 char buf[256];
297
298 if (!this->key)
299 return gpg_error (GPG_ERR_INV_OBJ);
300
301 err = gpgme_data_new (&out);
302 if (err)
303 goto leave;
304
305 err = gpgme_op_edit (ctx, key, list_handler, NULL, out);
306 if (err)
307 goto leave;
308
309 gpgme_data_rewind (out);
310 while (gpg_data_readline (out, buf, sizeof (buf) -1) > 0)
311 uid_inf_colon_handler (&inf, buf);
312
313 *r_uinf = inf;
314
315 leave:
316 if (out)
317 gpgme_data_release (out);
318 if (err) {
319 gpg_uid_info_release (inf);
320 *r_uinf = NULL;
321 }
322 return err;
323 }
324
325
326 /* Construct an object with the given key in @key. */
327 GpgKeyEdit::GpgKeyEdit (gpgme_key_t _key)
328 {
329 this->key = _key;
330 pass = NULL;
331 type = 0;
332 name = NULL;
333 cmt = NULL;
334 email = NULL;
335 cnt = 0;
336 cmd_sent = 0;
337 resval = 0;
338 gpgme_new (&ctx); /* FIXME */
339 }
340
341 /* Construct an object and fetch the key with the keyid @keyid. */
342 GpgKeyEdit::GpgKeyEdit (const char *_keyid)
343 {
344 get_pubkey (_keyid, &this->key);
345 pass = NULL;
346 type = 0;
347 name = NULL;
348 cmt = NULL;
349 email = NULL;
350 cmd_sent = 0;
351 resval = 0;
352 gpgme_new (&ctx); /* FIXME */
353 }
354
355 /* Delete the given object. */
356 GpgKeyEdit::~GpgKeyEdit (void)
357 {
358 free_if_alloc (name);
359 free_if_alloc (cmt);
360 free_if_alloc (email);
361 gpgme_release (ctx);
362 }
363
364
365 /* Reset the state of the object. */
366 void
367 GpgKeyEdit::reset (void)
368 {
369 cmd_sent = 0;
370 }
371
372
373 /* Return true if type has a non-zero value. */
374 bool
375 GpgKeyEdit::isValid (void)
376 {
377 return type != 0;
378 }
379
380
381 /* Return the GPGME key. */
382 gpgme_key_t
383 GpgKeyEdit::getKey (void)
384 {
385 return key;
386 }
387
388
389 /* Set the GPGME callback to @cb. The hook value can be
390 given in @cb_value. */
391 void
392 GpgKeyEdit::setCallback (gpgme_progress_cb_t cb, void *cb_value)
393 {
394 gpgme_set_progress_cb (ctx, cb, cb_value);
395 }
396
397 /* Set the passphrase to @pass. */
398 void
399 GpgKeyEdit::setPassphrase (const char *_pass)
400 {
401 this->pass = _pass;
402 }
403
404 /* Set the current key to @key. */
405 void
406 GpgKeyEdit::setKey (gpgme_key_t _key)
407 {
408 this->key = _key;
409 }
410
411 /* Set the keyid of the destination key to @keyid. */
412 void
413 GpgKeyEdit::setKeyID (const char *_keyid)
414 {
415 if (!_keyid)
416 return;
417 get_pubkey (_keyid, &this->key);
418 }
419
420
421 /* Set the local user for the operation to @locusr. */
422 void
423 GpgKeyEdit::setLocalUser (gpgme_key_t locusr)
424 {
425 gpgme_signers_add (ctx, locusr);
426 }
427
428 /* Set the result of the operation to @val. */
429 void
430 GpgKeyEdit::setResult (int val)
431 {
432 resval |= val;
433 }
434
435
436 /* Return the result of the operation. */
437 int
438 GpgKeyEdit::getResult(void)
439 {
440 return resval;
441 }
442
443
444
445 int
446 GpgKeyEdit::getType (void)
447 {
448 return type;
449 }
450
451 /* Sign the key stored in the object with the
452 signing mode @mode and the signature class @sig_class.
453 Return value: 0 on success. */
454 gpgme_error_t
455 GpgKeyEdit::signKey (int mode, int _sig_class, const char *_exp_date)
456 {
457 if (!this->key || !this->pass)
458 return gpg_error (GPG_ERR_INV_OBJ);
459
460 type = mode;
461 this->exp_date = _exp_date;
462 this->sig_class = _sig_class;
463 return gpg_editkey (this->ctx, this->key, this);
464 }
465
466
467 /* Set the ownertrust of the key stored in the object
468 to the trust value @trust.
469 Return value: 0 on success. */
470 gpgme_error_t
471 GpgKeyEdit::setTrust (gpgme_validity_t trust)
472 {
473 if (!this->key)
474 return gpg_error (GPG_ERR_INV_OBJ);
475
476 type = GPG_EDITKEY_TRUST;
477 this->trust_id = (int)trust;
478 return gpg_editkey (this->ctx, this->key, this);
479 }
480
481 /* Add a user ID to the given key with the @name as the
482 name, @cmt as the comment (or NULL) and @email as the email.
483 Return value: 0 on success. */
484 gpgme_error_t
485 GpgKeyEdit::addUserid (const char *_name, const char *_cmt, const char *_email)
486 {
487 if (!this->key || !this->pass)
488 return gpg_error (GPG_ERR_INV_OBJ);
489
490 type = GPG_EDITKEY_ADDUID;
491 free_if_alloc (this->name);
492 this->name = m_strdup (_name);
493 free_if_alloc (this->cmt);
494 this->cmt = NULL;
495 if (cmt != NULL)
496 this->cmt = m_strdup (_cmt);
497 free_if_alloc (this->email);
498 this->email = m_strdup (_email);
499 if (!this->email || !this->name)
500 BUG (NULL);
501 return gpg_editkey (this->ctx, this->key, this);
502 }
503
504 /* Delete the user-ID with the index @uid_index of the given key.
505 Return value: 0 on success. */
506 gpgme_error_t
507 GpgKeyEdit::delUserid (int _uid_index)
508 {
509 if (!this->key)
510 return gpg_error (GPG_ERR_INV_OBJ);
511
512 type = GPG_EDITKEY_DELUID;
513 this->uid_index = _uid_index;
514 return gpg_editkey (this->ctx, this->key, this);
515 }
516
517 /* Delete the subkey with the index @key_index.
518 Return value: 0 on success. */
519 gpgme_error_t
520 GpgKeyEdit::delKey (int _key_index)
521 {
522 if (!this->key)
523 return gpg_error (GPG_ERR_INV_OBJ);
524
525 type = GPG_EDITKEY_DELKEY;
526 this->key_index = _key_index;
527 return gpg_editkey (this->ctx, this->key, this);
528 }
529
530 /* Add a new subkey to the given key.
531 The new key will have @pubkey_algo as the algorithm
532 and a size of @pubkey_size bits. If valid > 0, the
533 key expires in @valid days.
534 Return value: 0 on success. */
535 gpgme_error_t
536 GpgKeyEdit::addSubkey (gpgme_pubkey_algo_t _pubkey_algo,
537 unsigned int _pubkey_size, long _valid)
538 {
539 if (!this->key || !this->pass)
540 return gpg_error (GPG_ERR_INV_OBJ);
541
542 type = GPG_EDITKEY_ADDKEY;
543 this->pubkey_algo = _pubkey_algo;
544 this->pubkey_size = _pubkey_size;
545 this->valid = _valid;
546 return gpg_editkey (this->ctx, this->key, this);
547 }
548
549 /* Change the passphrase of the given key to @new_pass.
550 If allow_empty != 0, it is allowed to provide an empty passphrase.
551 Return value: 0 on success. */
552 gpgme_error_t
553 GpgKeyEdit::changePassphrase (const char *_new_pass, int allow_empty)
554 {
555 if (!this->key || !this->pass)
556 return gpg_error (GPG_ERR_INV_OBJ);
557
558 type = GPG_EDITKEY_PASSWD;
559 this->new_pass = _new_pass;
560 this->flags = allow_empty? 1 : 0;
561 return gpg_editkey (this->ctx, this->key, this);
562 }
563
564 /* Set the primary user-ID of the given key to user-ID with
565 the index @uid_index.
566 Return value: 0 on success. */
567 gpgme_error_t
568 GpgKeyEdit::setPrimaryUserid (int _uid_index)
569 {
570 if (!this->key || !this->pass)
571 return gpg_error (GPG_ERR_INV_OBJ);
572
573 type = GPG_EDITKEY_PRIMARY;
574 this->uid_index = _uid_index;
575 return gpg_editkey (this->ctx, this->key, this);
576 }
577
578 /* Set the expire date of the subkey with the index @key_index.
579 @exp_timestamp is used to calculate the days the key is valid.
580 if @exp_days is true, exp_timestamp is already converted to days.
581 Return value: 0 on success. */
582 gpgme_error_t
583 GpgKeyEdit::setKeyExpireDate (int _key_index,
584 long exp_timestamp, bool exp_days)
585 {
586 if (!this->key || !this->pass)
587 return gpg_error (GPG_ERR_INV_OBJ);
588 if (!exp_days && exp_timestamp > 0 && exp_timestamp < time (NULL))
589 return gpg_error (GPG_ERR_INV_ARG);
590
591 type = GPG_EDITKEY_EXPIRE;
592 if (!exp_days && exp_timestamp > 0) {
593 valid = exp_timestamp - time (NULL);
594 valid /= 86400;
595 }
596 else
597 valid = exp_timestamp;
598 this->key_index = _key_index;
599 return gpg_editkey (this->ctx, this->key, this);
600 }
601
602 /* Revoke the userid given by the index @uid_index.
603 Return value: 0 on success. */
604 gpgme_error_t
605 GpgKeyEdit::revokeUserid (int _uid_index)
606 {
607 if (!this->key || !this->pass)
608 return gpg_error (GPG_ERR_INV_OBJ);
609
610 type = GPG_EDITKEY_REVUID;
611 this->uid_index = _uid_index;
612 return gpg_editkey (this->ctx, this->key, this);
613 }
614
615
616 /* Revoke a signature on the user-ID with the index @uid_index
617 and the signature index @sig_index.
618 Return value: 0 on success. */
619 gpgme_error_t
620 GpgKeyEdit::revokeSignature (int _uid_index, int _sig_index)
621 {
622 if (!this->key || !this->pass)
623 return gpg_error (GPG_ERR_INV_OBJ);
624
625 type = GPG_EDITKEY_REVSIG;
626 this->uid_index = _uid_index;
627 this->sig_index = _sig_index;
628 return gpg_editkey (this->ctx, this->key, this);
629 }
630
631
632 /* Revoke the subkey with the index @key_index. Optionally
633 a reason can be provided in @reason with a text to describe
634 more details in @cmt.
635 Return value: 0 on success. */
636 gpgme_error_t
637 GpgKeyEdit::revokeSubkey (int _key_index, int _reason, const char *_cmt)
638 {
639 if (!this->key || !this->pass)
640 return gpg_error (GPG_ERR_INV_OBJ);
641
642 type = GPG_EDITKEY_REVKEY;
643 this->key_index = _key_index;
644 this->reason = _reason;
645 free_if_alloc (this->cmt);
646 this->cmt = NULL;
647 if (_cmt)
648 this->cmt = m_strdup (_cmt);
649 return gpg_editkey (this->ctx, this->key, this);
650 }
651
652
653 /* Add a designated revoker to the key. @uid stores
654 the user-ID of the key who is allowed to be a
655 designated revoker.
656 Return value: 0 on success. */
657 gpgme_error_t
658 GpgKeyEdit::addDesignatedRevoker (const char *uid)
659 {
660 if (!this->key || !this->pass)
661 return gpg_error (GPG_ERR_INV_OBJ);
662
663 type = GPG_EDITKEY_ADDREV;
664 free_if_alloc (this->name);
665 this->name = m_strdup (uid);
666 return gpg_editkey (this->ctx, this->key, this);
667 }
668
669 /* Add a photo-ID to the key. The JPG image is given
670 in the file with the name @jpg_file.
671 Return value: 0 on success. */
672 gpgme_error_t
673 GpgKeyEdit::addPhotoid (const char *jpg_file)
674 {
675 if (!this->key || !this->pass)
676 return gpg_error (GPG_ERR_INV_OBJ);
677
678 type = GPG_EDITKEY_ADDPHOTO;
679 this->url = jpg_file;
680 return gpg_editkey (this->ctx, this->key, this);
681 }
682
683 /* Enable the given key. */
684 gpgme_error_t
685 GpgKeyEdit::enable (void)
686 {
687 if (!this->key)
688 return gpg_error (GPG_ERR_INV_OBJ);
689 type = GPG_EDITKEY_ENABLE;
690 return gpg_editkey (this->ctx, this->key, this);
691 }
692
693 /* Disable the given key. */
694 gpgme_error_t
695 GpgKeyEdit::disable (void)
696 {
697 if (!this->key)
698 return gpg_error (GPG_ERR_INV_OBJ);
699 type = GPG_EDITKEY_DISABLE;
700 return gpg_editkey (this->ctx, this->key, this);
701 }
702
703
704 /* Update the user-ID preferences of the user-ID with the
705 index @uid_index to the prefs given in @new_prefs.
706 Return value: 0 on success. */
707 gpgme_error_t
708 GpgKeyEdit::setUseridPreferences (int _uid_index, const char *new_prefs)
709 {
710 if (!this->key || !this->pass)
711 return gpg_error (GPG_ERR_INV_OBJ);
712 return 0;
713 }
714
715
716 /* Delete a signature from the user-ID with the index @uid_index.
717 The index of the signature is given in @sig_index.
718 Return value: 0 on success. */
719 gpgme_error_t
720 GpgKeyEdit::delUseridSignature (int _uid_index, int _sig_index)
721 {
722 if (!this->key)
723 return gpg_error (GPG_ERR_INV_OBJ);
724 type = GPG_EDITKEY_DELSIG;
725 this->uid_index = _uid_index;
726 this->sig_index = _sig_index;
727 return gpg_editkey (this->ctx, this->key, this);
728 }
729
730 /* Set the preferred keyserver for the given key to @url.
731 Return value: 0 on success. */
732 gpgme_error_t
733 GpgKeyEdit::setPreferredKeyserver (int _uid_index, const char *_url)
734 {
735 if (!this->key || !this->pass)
736 return gpg_error (GPG_ERR_INV_OBJ);
737 if (!url)
738 return gpg_error (GPG_ERR_INV_ARG);
739 type = GPG_EDITKEY_KEYSERV;
740 this->url = _url;
741 this->uid_index = _uid_index;
742 return gpg_editkey (this->ctx, this->key, this);
743 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26