1 |
/* wptKeyEdit.cpp - GPG key edit abstraction |
/* wptKeyEdit.cpp - GPG key edit abstraction |
2 |
* Copyright (C) 2005 Timo Schulz |
* Copyright (C) 2005 Timo Schulz |
3 |
|
* Copyright (C) 2005 g10 Code GmbH |
4 |
* |
* |
5 |
* This file is part of WinPT. |
* This file is part of WinPT. |
6 |
* |
* |
21 |
|
|
22 |
#include <windows.h> |
#include <windows.h> |
23 |
|
|
24 |
#include "w32gpgme.h" |
#include "gpgme.h" |
25 |
#include "wptCommonCtl.h" |
#include "wptCommonCtl.h" |
26 |
#include "wptContext.h" |
#include "wptContext.h" |
27 |
#include "wptKeyEdit.h" |
#include "wptKeyEdit.h" |
28 |
#include "wptTypes.h" |
#include "wptTypes.h" |
29 |
#include "wptW32API.h" |
#include "wptW32API.h" |
30 |
#include "wptGPG.h" |
#include "wptGPG.h" |
31 |
|
#include "wptErrors.h" |
32 |
|
|
33 |
|
|
34 |
/* Parse the colon status information of @line and store |
/* Parse the colon status information of @line and store |
35 |
the information in @rev. |
the information in @rev. |
41 |
gpg_desig_rev_t r, t; |
gpg_desig_rev_t r, t; |
42 |
int field = 0; |
int field = 0; |
43 |
|
|
44 |
if (!line || strlen (line) < 3 || strncmp (line, "rvk", 3)) |
if (!line || strlen (line) < 3) |
45 |
return gpg_error (GPG_ERR_EOF); |
return gpg_error (GPG_ERR_EOF); |
46 |
|
if (strncmp (line, "rvk", 3)) |
47 |
|
return 0; /* skip this line. */ |
48 |
|
|
49 |
|
log_debug ("rev_key: line=%s\r\n", line); |
50 |
|
|
51 |
r = (gpg_desig_rev_t)calloc (1, sizeof *r); |
r = (gpg_desig_rev_t)calloc (1, sizeof *r); |
52 |
if (!r) |
if (!r) |
69 |
if (pend == NULL) |
if (pend == NULL) |
70 |
break; |
break; |
71 |
switch (field) { |
switch (field) { |
72 |
case 3: r->pubkey_algo = (gpgme_pubkey_algo_t)atol (pend); break; |
case 4: r->pubkey_algo = (gpgme_pubkey_algo_t)atol (pend); break; |
73 |
case 9: strncpy (r->fpr, pend, 40); r->fpr[40] = 0; break; |
case 10: strncpy (r->fpr, pend, 40); r->fpr[40] = 0; break; |
74 |
} |
} |
75 |
} |
} |
76 |
if (p) |
if (p) |
77 |
free (p); |
free (p); |
85 |
static gpgme_error_t |
static gpgme_error_t |
86 |
uid_inf_colon_handler (gpg_uid_info_t *inf, char *line) |
uid_inf_colon_handler (gpg_uid_info_t *inf, char *line) |
87 |
{ |
{ |
88 |
|
gpg_uid_info_t i, t; |
89 |
char *p, *pend; |
char *p, *pend; |
90 |
int field = 0, len = 0; |
int field = 0, len = 0; |
|
gpg_uid_info_t i, t; |
|
91 |
|
|
92 |
if (!line || strlen (line) < 3 || strncmp (line, "uid", 3)) |
if (!line || strlen (line) < 3 || strncmp (line, "uid", 3)) |
93 |
return gpg_error (GPG_ERR_EOF); |
return gpg_error (GPG_ERR_EOF); |
120 |
i->name = (char *)calloc (1, strlen (pend)+1); |
i->name = (char *)calloc (1, strlen (pend)+1); |
121 |
if (!i->name) |
if (!i->name) |
122 |
return gpg_error (GPG_ERR_ENOMEM);; |
return gpg_error (GPG_ERR_ENOMEM);; |
123 |
/* XXX _gpgme_decode_c_string (pend, &i->name, strlen (pend)+ 1); */ |
gpg_decode_c_string (pend, &i->name, strlen (pend)+ 1); |
|
strcpy (i->name, pend); |
|
124 |
if (strchr (pend, '<') != NULL && strchr (pend, '>') != NULL) { |
if (strchr (pend, '<') != NULL && strchr (pend, '>') != NULL) { |
125 |
int pos = strchr (i->name, '<')- i->name + 1; |
int pos = strchr (i->name, '<')- i->name + 1; |
126 |
int end = strchr (i->name, '>') - i->name; |
int end = strchr (i->name, '>') - i->name; |
206 |
} |
} |
207 |
|
|
208 |
|
|
209 |
|
static gpgme_error_t |
210 |
|
list2_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd) |
211 |
|
{ |
212 |
|
DWORD n; |
213 |
|
const char *s; |
214 |
|
|
215 |
|
if (!strcmp (key, "keyedit.prompt")) { |
216 |
|
s = "quit\n"; |
217 |
|
WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL); |
218 |
|
} |
219 |
|
return 0; |
220 |
|
} |
221 |
|
|
222 |
|
/* Dummy handler to get the colon data and then quit. */ |
223 |
|
static gpgme_error_t |
224 |
|
list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd) |
225 |
|
{ |
226 |
|
static int step=0; |
227 |
|
const char *s=""; |
228 |
|
DWORD n; |
229 |
|
|
230 |
|
if (!strcmp (key, "keyedit.prompt") && step == 0) { |
231 |
|
step = 1; |
232 |
|
s = "list\n"; |
233 |
|
WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL); |
234 |
|
} |
235 |
|
else if (!strcmp (key, "keyedit.prompt") && step == 1) { |
236 |
|
step = 0; |
237 |
|
s = "quit\n"; |
238 |
|
WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL); |
239 |
|
} |
240 |
|
|
241 |
|
return 0; |
242 |
|
} |
243 |
|
|
244 |
|
|
245 |
/* Return all designated revokers for this key. If no revoker |
/* Return all designated revokers for this key. If no revoker |
246 |
was set, @r_rev is NULL. |
was set, @r_rev is NULL. |
247 |
Return value: 0 on success. */ |
Return value: 0 on success. */ |
251 |
gpgme_data_t out=NULL; |
gpgme_data_t out=NULL; |
252 |
gpg_desig_rev_t rev = NULL; |
gpg_desig_rev_t rev = NULL; |
253 |
gpgme_error_t err; |
gpgme_error_t err; |
254 |
char buf[200]; |
char buf[256]; |
255 |
|
|
256 |
if (!this->key) |
if (!this->key) |
257 |
return gpg_error (GPG_ERR_INV_OBJ); |
return gpg_error (GPG_ERR_INV_OBJ); |
260 |
if (err) |
if (err) |
261 |
goto leave; |
goto leave; |
262 |
|
|
263 |
err = gpgme_op_edit (ctx, key, NULL, NULL, out); |
err = gpgme_op_edit (ctx, key, list2_handler, NULL, out); |
264 |
if (err) |
if (err) |
265 |
goto leave; |
goto leave; |
266 |
|
|
267 |
while (gpg_data_readline (out, buf, 199)) |
gpgme_data_rewind (out); |
268 |
|
while (gpg_data_readline (out, buf, sizeof (buf)-1) > 0) |
269 |
rev_key_colon_handler (&rev, buf); |
rev_key_colon_handler (&rev, buf); |
270 |
*r_rev = rev; |
*r_rev = rev; |
271 |
|
|
272 |
leave: |
leave: |
273 |
if (out) |
if (out) |
288 |
gpgme_data_t out = NULL; |
gpgme_data_t out = NULL; |
289 |
gpgme_error_t err; |
gpgme_error_t err; |
290 |
gpg_uid_info_t inf = NULL; |
gpg_uid_info_t inf = NULL; |
291 |
char buf[200]; |
char buf[256]; |
292 |
|
|
293 |
if (!this->key) |
if (!this->key) |
294 |
return gpg_error (GPG_ERR_INV_OBJ); |
return gpg_error (GPG_ERR_INV_OBJ); |
297 |
if (err) |
if (err) |
298 |
goto leave; |
goto leave; |
299 |
|
|
300 |
err = gpgme_op_edit (ctx, key, NULL, NULL, out); |
err = gpgme_op_edit (ctx, key, list_handler, NULL, out); |
301 |
if (err) |
if (err) |
302 |
goto leave; |
goto leave; |
303 |
|
|
304 |
while (gpg_data_readline (out, buf, sizeof buf -1)) |
gpgme_data_rewind (out); |
305 |
|
while (gpg_data_readline (out, buf, sizeof (buf) -1) > 0) |
306 |
uid_inf_colon_handler (&inf, buf); |
uid_inf_colon_handler (&inf, buf); |
307 |
|
|
308 |
*r_uinf = inf; |
*r_uinf = inf; |
327 |
name = NULL; |
name = NULL; |
328 |
cmt = NULL; |
cmt = NULL; |
329 |
email = NULL; |
email = NULL; |
330 |
|
cnt = 0; |
331 |
|
cmd_sent = 0; |
332 |
|
resval = 0; |
333 |
gpgme_new (&ctx); /* FIXME */ |
gpgme_new (&ctx); /* FIXME */ |
334 |
} |
} |
335 |
|
|
342 |
name = NULL; |
name = NULL; |
343 |
cmt = NULL; |
cmt = NULL; |
344 |
email = NULL; |
email = NULL; |
345 |
|
cmd_sent = 0; |
346 |
|
resval = 0; |
347 |
gpgme_new (&ctx); /* FIXME */ |
gpgme_new (&ctx); /* FIXME */ |
348 |
} |
} |
349 |
|
|
357 |
} |
} |
358 |
|
|
359 |
|
|
360 |
|
/* Reset the state of the object. */ |
361 |
|
void |
362 |
|
GpgKeyEdit::reset (void) |
363 |
|
{ |
364 |
|
cmd_sent = 0; |
365 |
|
} |
366 |
|
|
367 |
|
|
368 |
/* Return true if type has a non-zero value. */ |
/* Return true if type has a non-zero value. */ |
369 |
bool |
bool |
370 |
GpgKeyEdit::isValid (void) |
GpgKeyEdit::isValid (void) |
403 |
this->key = key; |
this->key = key; |
404 |
} |
} |
405 |
|
|
406 |
|
/* Set the keyid of the destination key to @keyid. */ |
407 |
void |
void |
408 |
GpgKeyEdit::setKeyID (const char *keyid) |
GpgKeyEdit::setKeyID (const char *keyid) |
409 |
{ |
{ |
413 |
} |
} |
414 |
|
|
415 |
|
|
416 |
|
/* Set the local user for the operation to @locusr. */ |
417 |
void |
void |
418 |
GpgKeyEdit::setLocalUser (gpgme_key_t locusr) |
GpgKeyEdit::setLocalUser (gpgme_key_t locusr) |
419 |
{ |
{ |
420 |
gpgme_signers_add (ctx, locusr); |
gpgme_signers_add (ctx, locusr); |
421 |
} |
} |
422 |
|
|
423 |
|
/* Set the result of the operation to @val. */ |
424 |
|
void |
425 |
|
GpgKeyEdit::setResult (int val) |
426 |
|
{ |
427 |
|
resval |= val; |
428 |
|
} |
429 |
|
|
430 |
|
|
431 |
|
/* Return the result of the operation. */ |
432 |
|
int |
433 |
|
GpgKeyEdit::getResult(void) |
434 |
|
{ |
435 |
|
return resval; |
436 |
|
} |
437 |
|
|
438 |
|
|
439 |
/* Sign the key stored in the object with the |
/* Sign the key stored in the object with the |
440 |
signing mode @mode and the signature class @sig_class. |
signing mode @mode and the signature class @sig_class. |
478 |
free_if_alloc (this->name); |
free_if_alloc (this->name); |
479 |
this->name = m_strdup (name); |
this->name = m_strdup (name); |
480 |
free_if_alloc (this->cmt); |
free_if_alloc (this->cmt); |
481 |
this->cmt = m_strdup (cmt); |
this->cmt = NULL; |
482 |
|
if (cmt != NULL) |
483 |
|
this->cmt = m_strdup (cmt); |
484 |
free_if_alloc (this->email); |
free_if_alloc (this->email); |
485 |
this->email = m_strdup (email); |
this->email = m_strdup (email); |
486 |
if (!this->email || !this->name || !this->cmt) |
if (!this->email || !this->name) |
487 |
BUG (NULL); |
BUG (NULL); |
488 |
return gpg_editkey (this->ctx, this->key, this); |
return gpg_editkey (this->ctx, this->key, this); |
489 |
} |
} |
564 |
|
|
565 |
/* Set the expire date of the subkey with the index @key_index. |
/* Set the expire date of the subkey with the index @key_index. |
566 |
@exp_timestamp is used to calculate the days the key is valid. |
@exp_timestamp is used to calculate the days the key is valid. |
567 |
|
if @exp_days is true, exp_timestamp is already converted to days. |
568 |
Return value: 0 on success. */ |
Return value: 0 on success. */ |
569 |
gpgme_error_t |
gpgme_error_t |
570 |
GpgKeyEdit::setKeyExpireDate (int key_index, long exp_timestamp) |
GpgKeyEdit::setKeyExpireDate (int key_index, long exp_timestamp, bool exp_days) |
571 |
{ |
{ |
572 |
if (!this->key || !this->pass) |
if (!this->key || !this->pass) |
573 |
return gpg_error (GPG_ERR_INV_OBJ); |
return gpg_error (GPG_ERR_INV_OBJ); |
574 |
if (exp_timestamp > 0 && exp_timestamp < time (NULL)) |
if (!exp_days && exp_timestamp > 0 && exp_timestamp < time (NULL)) |
575 |
return gpg_error (GPG_ERR_INV_ARG); |
return gpg_error (GPG_ERR_INV_ARG); |
576 |
|
|
577 |
valid = 0; |
type = GPG_EDITKEY_EXPIRE; |
578 |
if (exp_timestamp > 0) { |
if (!exp_days && exp_timestamp > 0) { |
579 |
valid = exp_timestamp - time (NULL); |
valid = exp_timestamp - time (NULL); |
580 |
valid /= 86400; |
valid /= 86400; |
|
type = GPG_EDITKEY_EXPIRE; |
|
581 |
} |
} |
582 |
|
else |
583 |
|
valid = exp_timestamp; |
584 |
this->key_index = key_index; |
this->key_index = key_index; |
585 |
return gpg_editkey (this->ctx, this->key, this); |
return gpg_editkey (this->ctx, this->key, this); |
586 |
} |
} |
587 |
|
|
588 |
|
/* Revoke the userid given by the index @uid_index. |
589 |
|
Return value: 0 on success. */ |
590 |
|
gpgme_error_t |
591 |
|
GpgKeyEdit::revokeUserid (int uid_index) |
592 |
|
{ |
593 |
|
if (!this->key || !this->pass) |
594 |
|
return gpg_error (GPG_ERR_INV_OBJ); |
595 |
|
|
596 |
|
type = GPG_EDITKEY_REVUID; |
597 |
|
this->uid_index = uid_index; |
598 |
|
return gpg_editkey (this->ctx, this->key, this); |
599 |
|
} |
600 |
|
|
601 |
|
|
602 |
/* Revoke a signature on the user-ID with the index @uid_index |
/* Revoke a signature on the user-ID with the index @uid_index |
603 |
and the signature index @sig_index. |
and the signature index @sig_index. |
629 |
this->key_index = key_index; |
this->key_index = key_index; |
630 |
this->reason = reason; |
this->reason = reason; |
631 |
free_if_alloc (this->cmt); |
free_if_alloc (this->cmt); |
632 |
this->cmt = m_strdup (cmt); |
this->cmt = NULL; |
633 |
return gpg_editkey (this->ctx, this->key, this); |
if (cmt) |
634 |
} |
this->cmt = m_strdup (cmt); |
|
|
|
|
|
|
|
/* Revoke an entire key. With the reason given in @reason |
|
|
and the description in @cmt. |
|
|
Return value: 0 on success. */ |
|
|
gpgme_error_t |
|
|
GpgKeyEdit::revokeKey (int reason, const char *cmt) |
|
|
{ |
|
|
if (!this->key || !this->pass) |
|
|
return gpg_error (GPG_ERR_INV_OBJ); |
|
|
|
|
|
type = GPG_EDITKEY_REVOKE; |
|
|
this->reason = reason; |
|
|
free_if_alloc (this->cmt); |
|
|
this->cmt = m_strdup (cmt); |
|
635 |
return gpg_editkey (this->ctx, this->key, this); |
return gpg_editkey (this->ctx, this->key, this); |
636 |
} |
} |
637 |
|
|
695 |
{ |
{ |
696 |
if (!this->key || !this->pass) |
if (!this->key || !this->pass) |
697 |
return gpg_error (GPG_ERR_INV_OBJ); |
return gpg_error (GPG_ERR_INV_OBJ); |
698 |
return GPG_ERR_NO_ERROR; |
return 0; |
699 |
} |
} |
700 |
|
|
701 |
|
|
703 |
The index of the signature is given in @sig_index. |
The index of the signature is given in @sig_index. |
704 |
Return value: 0 on success. */ |
Return value: 0 on success. */ |
705 |
gpgme_error_t |
gpgme_error_t |
706 |
GpgKeyEdit::deleteUseridSignature (int uid_index, int sig_index) |
GpgKeyEdit::delUseridSignature (int uid_index, int sig_index) |
707 |
{ |
{ |
708 |
if (!this->key) |
if (!this->key) |
709 |
return gpg_error (GPG_ERR_INV_OBJ); |
return gpg_error (GPG_ERR_INV_OBJ); |