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

Diff of /trunk/Src/wptKeyEdit.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 23 by twoaday, Fri Sep 30 10:10:16 2005 UTC revision 234 by twoaday, Tue Jun 27 10:16:41 2006 UTC
# Line 1  Line 1 
1  /* wptKeyEdit.cpp - GPG key edit abstraction  /* wptKeyEdit.cpp - GPG key edit abstraction
2   *      Copyright (C) 2005 Timo Schulz   *      Copyright (C) 2005, 2006 Timo Schulz
3   *   *      Copyright (C) 2005 g10 Code GmbH
4   * This file is part of WinPT.   *
5   *   * This file is part of WinPT.
6   * WinPT is free software; you can redistribute it and/or   *
7   * modify it under the terms of the GNU General Public License   * WinPT is free software; you can redistribute it and/or
8   * as published by the Free Software Foundation; either version 2   * modify it under the terms of the GNU General Public License
9   * of the License, or (at your option) any later version.   * as published by the Free Software Foundation; either version 2
10   *     * of the License, or (at your option) any later version.
11   * WinPT is distributed in the hope that it will be useful,   *  
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * WinPT is distributed in the hope that it will be useful,
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * General Public License for more details.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   *   * General Public License for more details.
16   * You should have received a copy of the GNU General Public License   *
17   * along with WinPT; if not, write to the Free Software Foundation,   * You should have received a copy of the GNU General Public License
18   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   * 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  #include <windows.h>  
22    #ifdef HAVE_CONFIG_H
23  #include "w32gpgme.h"  #include <config.h>
24  #include "wptCommonCtl.h"  #endif
25  #include "wptContext.h"  
26  #include "wptKeyEdit.h"  #include <windows.h>
27  #include "wptTypes.h"  #include <time.h>
28  #include "wptW32API.h"  
29  #include "wptGPG.h"  #include "gpgme.h"
30    #include "wptCommonCtl.h"
31  /* Parse the colon status information of @line and store  #include "wptContext.h"
32     the information in @rev.  #include "wptKeyEdit.h"
33     Return value: 0 on success. */  #include "wptTypes.h"
34  static gpgme_error_t  #include "wptW32API.h"
35  rev_key_colon_handler (gpg_desig_rev_t *rev, char *line)  #include "wptGPG.h"
36  {  #include "wptErrors.h"
37      char *p, *pend;  #include "wptUTF8.h"
38      gpg_desig_rev_t r, t;  
39      int field = 0;  
40    /* Parse the colon status information of @line and store
41      if (!line || strlen (line) < 3 || strncmp (line, "rvk", 3))     the information in @rev.
42          return gpg_error (GPG_ERR_EOF);     Return value: 0 on success. */
43    static gpgme_error_t
44      r = (gpg_desig_rev_t)calloc (1, sizeof *r);  rev_key_colon_handler (gpg_desig_rev_t *rev, char *line)
45      if (!r)  {
46          return gpg_error (GPG_ERR_ENOMEM);      char *p, *pend;
47      if (!*rev)      gpg_desig_rev_t r, t;
48          *rev = r;      int field = 0;
49      else {  
50          for (t=*rev; t->next; t=t->next)      if (!line || strlen (line) < 3)
51              ;          return gpg_error (GPG_ERR_EOF);
52          t->next = r;      if (strncmp (line, "rvk", 3))
53      }          return 0; /* skip this line. */
54    
55      p = strdup (line);      log_debug ("rev_key: line=%s\r\n", line);
56      if (!p)  
57          return gpg_error (GPG_ERR_ENOMEM);      r = (gpg_desig_rev_t)calloc (1, sizeof *r);
58        if (!r)
59      for (;;) {          return gpg_error (GPG_ERR_ENOMEM);
60          field++;      if (!*rev)
61          pend = strsep (&p, ":");          *rev = r;
62          if (pend == NULL)      else {
63              break;          for (t=*rev; t->next; t=t->next)
64          switch (field) {              ;
65          case 3: r->pubkey_algo = (gpgme_pubkey_algo_t)atol (pend); break;          t->next = r;
66          case 9: strncpy (r->fpr, pend, 40); r->fpr[40] = 0; break;      }
67          }  
68      }      p = strdup (line);
69      if (p)      if (!p)
70          free (p);          return gpg_error (GPG_ERR_ENOMEM);
71      return 0;  
72  }      for (;;) {
73            field++;
74            pend = strsep (&p, ":");
75  /* Parse the colon data output of edit key from @line and          if (pend == NULL)
76     store the information in the @inf context.              break;
77     Return value: 0 on success. */          switch (field) {
78  static gpgme_error_t          case  4:
79  uid_inf_colon_handler (gpg_uid_info_t *inf, char *line)              r->pubkey_algo = (gpgme_pubkey_algo_t)atol (pend);
80  {              break;
81      char *p, *pend;  
82      int field = 0, len = 0;          case 10:
83      gpg_uid_info_t i, t;              strncpy (r->fpr, pend, 40);
84                r->fpr[40] = 0;
85      if (!line || strlen (line) < 3 || strncmp (line, "uid", 3))              break;
86          return gpg_error (GPG_ERR_EOF);          }      
87        }
88      i = (gpg_uid_info_t)calloc (1, sizeof *i);      if (p)
89      if (!i)          free (p);
90          return gpg_error (GPG_ERR_ENOMEM);      return 0;
91      if (!*inf)  }
92          *inf = i;  
93      else {  
94          for (t=*inf; t->next; t=t->next)  /* Parse the colon data output of edit key from @line and
95              ;     store the information in the @inf context.
96          t->next = i;     Return value: 0 on success. */
97      }  static gpgme_error_t
98    uid_inf_colon_handler (gpg_uid_info_t *inf, char *line)
99      p = strdup (line);  {
100      if (!p)      gpg_uid_info_t i, t;
101          return gpg_error (GPG_ERR_ENOMEM);;      char *p, *pend;
102      for (;;) {      char *name;
103          field++;      int field = 0, len = 0;
104          pend = strsep (&p, ":");  
105          if (pend == NULL)      if (!line || strlen (line) < 3 || strncmp (line, "uid", 3))
106              break;          return gpg_error (GPG_ERR_EOF);
107    
108          switch (field) {      i = (gpg_uid_info_t)calloc (1, sizeof *i);
109          case 2: /* trust info */      if (!i)
110              break;          return gpg_error (GPG_ERR_ENOMEM);
111        if (!*inf)
112          case 10: /* user ID */          *inf = i;
113              i->name = (char *)calloc (1, strlen (pend)+1);      else {
114              if (!i->name)          for (t=*inf; t->next; t=t->next)
115                  return gpg_error (GPG_ERR_ENOMEM);;              ;
116              /* XXX _gpgme_decode_c_string (pend, &i->name, strlen (pend)+ 1); */          t->next = i;
117              strcpy (i->name, pend);      }
118              if (strchr (pend, '<') != NULL && strchr (pend, '>') != NULL) {  
119                  int pos = strchr (i->name, '<')- i->name + 1;      p = strdup (line);
120                  int end = strchr (i->name, '>') - i->name;      if (!p)
121                  i->email = (char*) calloc (1, end-pos+2);          return gpg_error (GPG_ERR_ENOMEM);;
122                  if (!i->email)      for (;;) {
123                      return gpg_error (GPG_ERR_ENOMEM);;          field++;
124                  memcpy (i->email, i->name+pos, (end-pos));          pend = strsep (&p, ":");
125              }          if (pend == NULL)
126              break;              break;
127    
128          case 13: /* preferences */          switch (field) {
129              if (strstr (pend, "mdc")) {          case 2: /* trust info */
130                  len = strlen (pend) - 4; /* ,mdc */              break;
131                  if (strstr (pend, "no-ks-modify")) {  
132                      i->flags.no_ks_modify = 1;          case 10: /* user ID */
133                      len -= 13; /* ,no-ks-modify */              name = (char *)calloc (1, strlen (pend)+1);
134                  }              if (!name)
135                  i->prefs = (char*)calloc (1, len+1);                  return gpg_error (GPG_ERR_ENOMEM);;
136                  if (!i->prefs)              gpg_decode_c_string (pend, &name, strlen (pend)+ 1);
137                      return gpg_error (GPG_ERR_ENOMEM);              i->name = utf8_to_native (name);
138                  memcpy (i->prefs, pend, len);              safe_free (name);
139                  i->prefs[len] = '\0';              if (strchr (pend, '<') != NULL && strchr (pend, '>') != NULL) {
140                  i->flags.mdc = 1;                  int pos = strchr (i->name, '<')- i->name + 1;
141              }                  int end = strchr (i->name, '>') - i->name;
142              else {                  i->email = (char*) calloc (1, end-pos+2);
143                  i->prefs = strdup (pend);                  if (!i->email)
144                  if (!i->prefs)                      return gpg_error (GPG_ERR_ENOMEM);;
145                      return gpg_error (GPG_ERR_ENOMEM);                  memcpy (i->email, i->name+pos, (end-pos));
146                  i->flags.mdc = 0;                            }
147              }              break;
148              break;  
149            case 13: /* preferences */
150          case 14: /* index/flags */              if (strstr (pend, "mdc")) {
151              i->index = atol (pend);                  const char *s = "no-ks-modify";
152              if (strchr (pend, 'r'))                  len = strlen (pend) - 4; /* ,mdc */
153                  i->flags.revoked = 1;                  if (strstr (pend, s)) {
154              if (strchr (pend, 'p'))                      i->flags.no_ks_modify = 1;
155                  i->flags.primary = 1;                      len -= strlen (s)+1; /* ',' + s */
156              break;                  }
157          }                  i->prefs = (char*)calloc (1, len+1);
158      }                  if (!i->prefs)
159      if (p)                      return gpg_error (GPG_ERR_ENOMEM);
160          free (p);                  memcpy (i->prefs, pend, len);
161      return 0;                  i->prefs[len] = '\0';
162  }                  i->flags.mdc = 1;
163                }
164                else {
165  /* Release the context in @inf. */                  i->prefs = strdup (pend);
166  void                  if (!i->prefs)
167  gpg_uid_info_release (gpg_uid_info_t list)                      return gpg_error (GPG_ERR_ENOMEM);
168  {                  i->flags.mdc = 0;              
169      gpg_uid_info_t i;              }
170                  break;
171      while (list) {  
172          i = list->next;          case 14: /* index/flags */
173          if (list->name) {              i->index = atoi (pend);
174              if (list->name)                        if (strchr (pend, 'r'))
175                  free (list->name);                  i->flags.revoked = 1;
176              list->name = NULL;              if (strchr (pend, 'p'))
177          }                  i->flags.primary = 1;
178          if (list->prefs) {              break;
179              if (list->prefs)          }
180                  free (list->prefs);      }
181              list->prefs = NULL;      if (p)
182          }                free (p);
183          free (list);      return 0;
184          list = i;  }
185      }  
186  }  
187    /* Release the context in @inf. */
188    void
189  /* Release the context in @rev. */  gpg_uid_info_release (gpg_uid_info_t list)
190  void  {
191  gpg_desig_rev_release (gpg_desig_rev_t rev)      gpg_uid_info_t i;
192  {    
193      gpg_desig_rev_t r;      while (list) {
194            i = list->next;
195      while (rev) {          if (list->name) {
196          r = rev->next;              if (list->name)          
197          free (rev);                  free (list->name);
198          rev = r;              list->name = NULL;
199      }          }
200  }          if (list->prefs) {
201                if (list->prefs)
202                    free (list->prefs);
203  /* Return all designated revokers for this key. If no revoker              list->prefs = NULL;
204     was set, @r_rev is NULL.          }      
205     Return value: 0 on success. */          free (list);
206  gpgme_error_t          list = i;
207  GpgKeyEdit::getDesignatedRevoker (gpg_desig_rev_t *r_rev)      }
208  {  }
209      gpgme_data_t out=NULL;  
210      gpg_desig_rev_t rev = NULL;  
211      gpgme_error_t err;  /* Release the context in @rev. */
212      char buf[200];  void
213    gpg_desig_rev_release (gpg_desig_rev_t rev)
214      if (!this->key)  {
215          return gpg_error (GPG_ERR_INV_OBJ);      gpg_desig_rev_t r;
216    
217      err = gpgme_data_new (&out);      while (rev) {
218      if (err)          r = rev->next;
219          goto leave;          free (rev);
220            rev = r;
221      err = gpgme_op_edit (ctx, key, NULL, NULL, out);      }
222      if (err)  }
223          goto leave;  
224    
225      while (gpg_data_readline (out, buf, 199))  static gpgme_error_t
226          rev_key_colon_handler (&rev, buf);  list2_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
227      *r_rev = rev;  {
228        DWORD n;
229  leave:      const char *s;
230      if (out)  
231          gpgme_data_release (out);      if (!strcmp (key, "keyedit.prompt")) {
232      if (err) {          s = "quit\n";
233          gpg_desig_rev_release (rev);          WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
234          *r_rev = NULL;      }    
235      }      return 0;
236      return err;  }
237  }  
238    
239  /* Retrieve all user ID information of the key set via setKey  /* Dummy handler to get the colon data and then quit. */
240     in @r_inf. The result also contains the user ID number which  static gpgme_error_t
241     is needed to securely delete the user-ID. */  list_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd)
242  gpgme_error_t  {
243  GpgKeyEdit::getUseridInfo (gpg_uid_info_t *r_uinf)      static int step=0;
244  {      const char *s="";
245      gpgme_data_t out = NULL;          DWORD n;
246      gpgme_error_t err;  
247      gpg_uid_info_t inf = NULL;      if (!strcmp (key, "keyedit.prompt") && step == 0) {
248      char buf[200];          step = 1;
249            s = "list\n";
250      if (!this->key)          WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
251          return gpg_error (GPG_ERR_INV_OBJ);      }
252        else if (!strcmp (key, "keyedit.prompt") && step == 1) {
253      err = gpgme_data_new (&out);          step = 0;
254      if (err)          s = "quit\n";
255          goto leave;          WriteFile ((HANDLE)fd, s, strlen (s), &n, NULL);
256        }
257      err = gpgme_op_edit (ctx, key, NULL, NULL, out);  
258      if (err)      return 0;
259          goto leave;  }
260        
261      while (gpg_data_readline (out, buf, sizeof buf -1))  
262          uid_inf_colon_handler (&inf, buf);  /* Return all designated revokers for this key. If no revoker
263       was set, @r_rev is NULL.
264      *r_uinf = inf;     Return value: 0 on success. */
265    gpgme_error_t
266  leave:  GpgKeyEdit::getDesignatedRevoker (gpg_desig_rev_t *r_rev)
267      if (out)  {
268          gpgme_data_release (out);      gpgme_data_t out = NULL;
269      if (err) {      gpg_desig_rev_t rev = NULL;
270          gpg_uid_info_release (inf);      gpgme_error_t err;
271          *r_uinf = NULL;      char buf[256];
272      }  
273      return err;      if (!this->key)
274  }          return gpg_error (GPG_ERR_INV_OBJ);
275    
276        err = gpgme_data_new (&out);
277  /* Construct an object with the given key in @key. */      if (err)
278  GpgKeyEdit::GpgKeyEdit (gpgme_key_t key)          goto leave;
279  {  
280      this->key = key;      err = gpgme_op_edit (ctx, key, list2_handler, NULL, out);
281      pass = NULL;      if (err)
282      type = 0;          goto leave;
283      name = NULL;      
284      cmt = NULL;      gpgme_data_rewind (out);
285      email = NULL;      while (gpg_data_readline (out, buf, sizeof (buf)-1) > 0)
286      gpgme_new (&ctx); /* FIXME */          rev_key_colon_handler (&rev, buf);
287  }      *r_rev = rev;
288    
289  /* Construct an object and fetch the key with the keyid @keyid. */  leave:
290  GpgKeyEdit::GpgKeyEdit (const char *keyid)      if (out)
291  {          gpgme_data_release (out);
292      get_pubkey (keyid, &this->key);      if (err) {
293      pass = NULL;          gpg_desig_rev_release (rev);
294      type = 0;          *r_rev = NULL;
295      name = NULL;      }
296      cmt = NULL;      return err;
297      email = NULL;  }
298      gpgme_new (&ctx); /* FIXME */  
299  }  
300    /* Retrieve all user ID information of the key set via setKey
301  /* Delete the given object. */     in @r_inf. The result also contains the user ID number which
302  GpgKeyEdit::~GpgKeyEdit (void)     is needed to securely delete the user-ID. */
303  {  gpgme_error_t
304      free_if_alloc (name);  GpgKeyEdit::getUseridInfo (gpg_uid_info_t *r_uinf)
305      free_if_alloc (cmt);  {
306      free_if_alloc (email);      gpgme_data_t out = NULL;    
307      gpgme_release (ctx);      gpgme_error_t err;
308  }      gpg_uid_info_t inf = NULL;
309        char buf[256];
310    
311  /* Return true if type has a non-zero value. */      if (!this->key)
312  bool          return gpg_error (GPG_ERR_INV_OBJ);
313  GpgKeyEdit::isValid (void)  
314  {      err = gpgme_data_new (&out);
315      return type != 0;      if (err)
316  }          goto leave;
317    
318        err = gpgme_op_edit (ctx, key, list_handler, NULL, out);
319  /* Return the GPGME key. */      if (err)
320  gpgme_key_t          goto leave;
321  GpgKeyEdit::getKey (void)      
322  {      gpgme_data_rewind (out);
323      return key;      while (gpg_data_readline (out, buf, sizeof (buf) -1) > 0)
324  }          uid_inf_colon_handler (&inf, buf);
325    
326        *r_uinf = inf;
327  /* Set the GPGME callback to @cb. The hook value can be  
328     given in @cb_value. */  leave:
329  void      if (out)
330  GpgKeyEdit::setCallback (gpgme_progress_cb_t cb, void *cb_value)          gpgme_data_release (out);
331  {      if (err) {
332      gpgme_set_progress_cb (ctx, cb, cb_value);          gpg_uid_info_release (inf);
333  }          *r_uinf = NULL;
334        }
335  /* Set the passphrase to @pass. */      return err;
336  void  }
337  GpgKeyEdit::setPassphrase (const char *pass)  
338  {  
339      this->pass = pass;  /* Clear object. */
340  }  void
341    GpgKeyEdit::clear (void)
342  /* Set the current key to @key. */  {
343  void      pass = NULL;    
344  GpgKeyEdit::setKey (gpgme_key_t key)      name = NULL;
345  {      cmt = NULL;
346      this->key = key;      email = NULL;
347  }      type = 0;
348        cnt = 0;
349  void      cmd_sent = 0;
350  GpgKeyEdit::setKeyID (const char *keyid)      resval = 0;
351  {      uid_index = sig_index = key_index = -1;
352      if (!keyid)      key_has_passwd = true;
353          return;  }
354      get_pubkey (keyid, &this->key);  
355  }  
356    /* Construct an object with the given key in @key. */
357    GpgKeyEdit::GpgKeyEdit (gpgme_key_t _key)
358  void  {
359  GpgKeyEdit::setLocalUser (gpgme_key_t locusr)      clear ();
360  {      this->key = _key;
361      gpgme_signers_add (ctx, locusr);      gpgme_new (&ctx); /* FIXME */
362  }  }
363    
364    /* Construct an object and fetch the key with the keyid @keyid. */
365  /* Sign the key stored in the object with the  GpgKeyEdit::GpgKeyEdit (const char *_keyid)
366     signing mode @mode and the signature class @sig_class.  {
367     Return value: 0 on success. */      clear ();
368  gpgme_error_t      get_pubkey (_keyid, &this->key);
369  GpgKeyEdit::signKey (int mode, int sig_class, const char *exp_date)      gpgme_new (&ctx); /* FIXME */    
370  {  }
371      if (!this->key || !this->pass)  
372          return gpg_error (GPG_ERR_INV_OBJ);  /* Delete the given object. */
373    GpgKeyEdit::~GpgKeyEdit (void)
374      type = mode;  {
375      this->exp_date = exp_date;      free_if_alloc (name);
376      this->sig_class = sig_class;      free_if_alloc (cmt);
377      return gpg_editkey (this->ctx, this->key, this);      free_if_alloc (email);
378  }      gpgme_release (ctx);
379    }
380  /* Set the ownertrust of the key stored in the object  
381     to the trust value @trust.  
382     Return value: 0 on success. */  /* Reset the state of the object. */
383  gpgme_error_t  void
384  GpgKeyEdit::setTrust (gpgme_validity_t trust)  GpgKeyEdit::reset (void)
385  {  {
386      if (!this->key)      cmd_sent = 0;
387          return gpg_error (GPG_ERR_INV_OBJ);      cnt = 0;
388    }
389      type = GPG_EDITKEY_TRUST;  
390      this->trust_id = (int)trust;  
391      return gpg_editkey (this->ctx, this->key, this);  /* Return true if type has a non-zero value. */
392  }  bool
393    GpgKeyEdit::isValid (void)
394  /* Add a user ID to the given key with the @name as the  {
395     name, @cmt as the comment (or NULL) and @email as the email.      return type != 0;
396     Return value: 0 on success. */  }
397  gpgme_error_t  
398  GpgKeyEdit::addUserid (const char *name, const char *cmt, const char *email)  
399  {  /* Return the GPGME key. */
400      if (!this->key || !this->pass)  gpgme_key_t
401          return gpg_error (GPG_ERR_INV_OBJ);  GpgKeyEdit::getKey (void)
402    {
403      type = GPG_EDITKEY_ADDUID;      return key;
404      free_if_alloc (this->name);  }
405      this->name = m_strdup (name);  
406      free_if_alloc (this->cmt);  
407      this->cmt = m_strdup (cmt);  /* Set the GPGME callback to @cb. The hook value can be
408      free_if_alloc (this->email);     given in @cb_value. */
409      this->email = m_strdup (email);  void
410      if (!this->email || !this->name || !this->cmt)  GpgKeyEdit::setCallback (gpgme_progress_cb_t cb, void *cb_value)
411          BUG (NULL);  {
412      return gpg_editkey (this->ctx, this->key, this);      gpgme_set_progress_cb (ctx, cb, cb_value);
413  }  }
414    
415  /* Delete the user-ID with the index @uid_index of the given key.  
416     Return value: 0 on success. */  /* Clear the stored passphrase. */
417  gpgme_error_t  void
418  GpgKeyEdit::delUserid (int uid_index)  GpgKeyEdit::clearPassphrase (void)
419  {  {
420      if (!this->key)      if (pass)
421          return gpg_error (GPG_ERR_INV_OBJ);          pass = NULL;
422    }
423      type = GPG_EDITKEY_DELUID;  
424      this->uid_index = uid_index;  
425      return gpg_editkey (this->ctx, this->key, this);  
426  }  /* Inidicate that a key is protected by  a passphrase or not. */
427    void
428  /* Delete the subkey with the index @key_index.  GpgKeyEdit::setNoPassphrase (bool val)
429     Return value: 0 on success. */  {
430  gpgme_error_t      key_has_passwd = !val;
431  GpgKeyEdit::delKey (int key_index)  }
432  {  
433      if (!this->key)  /* Set the passphrase to @pass. */
434          return gpg_error (GPG_ERR_INV_OBJ);  void
435    GpgKeyEdit::setPassphrase (const char *_pass)
436      type = GPG_EDITKEY_DELKEY;  {
437      this->key_index = key_index;      this->pass = _pass;
438      return gpg_editkey (this->ctx, this->key, this);  }
439  }  
440    /* Set the current key to @key. */
441  /* Add a new subkey to the given key.  void
442     The new key will have @pubkey_algo as the algorithm  GpgKeyEdit::setKey (gpgme_key_t _key)
443     and a size of @pubkey_size bits. If valid > 0, the  {
444     key expires in @valid days.      this->key = _key;
445     Return value: 0 on success. */  }
446  gpgme_error_t  
447  GpgKeyEdit::addSubkey (gpgme_pubkey_algo_t pubkey_algo, unsigned int pubkey_size,  /* Set the keyid of the destination key to @keyid. */
448                         long valid)  void
449  {  GpgKeyEdit::setKeyID (const char *_keyid)
450      if (!this->key || !this->pass)  {
451          return gpg_error (GPG_ERR_INV_OBJ);      if (!_keyid)
452            return;
453      type = GPG_EDITKEY_ADDKEY;      get_pubkey (_keyid, &this->key);
454      this->pubkey_algo = pubkey_algo;  }
455      this->pubkey_size = pubkey_size;  
456      this->valid = valid;  
457      return gpg_editkey (this->ctx, this->key, this);  /* Set the local user for the operation to @locusr. */
458  }  void
459    GpgKeyEdit::setLocalUser (gpgme_key_t locusr)
460  /* Change the passphrase of the given key to @new_pass.  {
461     If allow_empty != 0, it is allowed to provide an empty passphrase.      gpgme_signers_add (ctx, locusr);
462     Return value: 0 on success. */  }
463  gpgme_error_t  
464  GpgKeyEdit::changePassphrase (const char *new_pass, int allow_empty)  /* Set the result of the operation to @val. */
465  {  void
466      if (!this->key || !this->pass)  GpgKeyEdit::setResult (int val)
467          return gpg_error (GPG_ERR_INV_OBJ);  {
468            resval |= val;
469      type = GPG_EDITKEY_PASSWD;  }
470      this->new_pass = new_pass;  
471      this->flags = allow_empty? 1 : 0;  
472      return gpg_editkey (this->ctx, this->key, this);  /* Return the result of the operation. */
473  }  int
474    GpgKeyEdit::getResult(void)
475  /* Set the primary user-ID of the given key to user-ID with  {
476     the index @uid_index.      return resval;
477     Return value: 0 on success. */  }
478  gpgme_error_t  
479  GpgKeyEdit::setPrimaryUserid (int uid_index)  
480  {  /* Return the amount of days the key is valid. */
481      if (!this->key || !this->pass)  int
482          return gpg_error (GPG_ERR_INV_OBJ);  GpgKeyEdit::getValidDays (void)
483    {
484      type = GPG_EDITKEY_PRIMARY;      return valid;
485      this->uid_index = uid_index;  }
486      return gpg_editkey (this->ctx, this->key, this);  
487  }  
488    int
489  /* Set the expire date of the subkey with the index @key_index.  GpgKeyEdit::getType (void)
490     @exp_timestamp is used to calculate the days the key is valid.  {
491     Return value: 0 on success. */      return type;
492  gpgme_error_t  }
493  GpgKeyEdit::setKeyExpireDate (int key_index, long exp_timestamp)  
494  {  
495      if (!this->key || !this->pass)  /* Add the notation data from @notation to the user ID
496          return gpg_error (GPG_ERR_INV_OBJ);     with the index @_uid_idx.
497      if (exp_timestamp > 0 && exp_timestamp < time (NULL))     Return value: 0 on success.  */
498          return gpg_error (GPG_ERR_INV_ARG);  gpgme_error_t
499    GpgKeyEdit::addNotation (int _uid_idx, const char *_notation)
500      valid = 0;  {
501      if (exp_timestamp > 0) {      if (!key)
502          valid = exp_timestamp - time (NULL);          return gpg_error (GPG_ERR_INV_OBJ);
503          valid /= 86400;      if (key_has_passwd && !this->pass)
504          type = GPG_EDITKEY_EXPIRE;          return gpg_error (GPG_ERR_INV_PASSPHRASE);
505      }  
506      this->key_index = key_index;      type = GPG_EDITKEY_NOTATION;
507      return gpg_editkey (this->ctx, this->key, this);      this->uid_index = _uid_idx;
508  }      this->notation = (char*)_notation;
509        return gpg_editkey (this->ctx, this->key, this);
510    }
511  /* Revoke a signature on the user-ID with the index @uid_index  
512     and the signature index @sig_index.  
513     Return value: 0 on success. */  /* Sign the key stored in the object with the
514  gpgme_error_t     signing mode @mode and the signature class @sig_class.
515  GpgKeyEdit::revokeSignature (int uid_index, int sig_index)     Return value: 0 on success. */
516  {  gpgme_error_t
517      if (!this->key || !this->pass)  GpgKeyEdit::signKey (int mode, int _sig_class, const char *_exp_date)
518          return gpg_error (GPG_ERR_INV_OBJ);  {
519        if (!this->key)
520      type = GPG_EDITKEY_REVSIG;          return gpg_error (GPG_ERR_INV_OBJ);
521      this->uid_index = uid_index;      if (key_has_passwd && !this->pass)
522      this->sig_index = sig_index;          return gpg_error (GPG_ERR_INV_PASSPHRASE);
523      return gpg_editkey (this->ctx, this->key, this);  
524  }      type = mode;
525        this->exp_date = _exp_date;
526        this->sig_class = _sig_class;
527  /* Revoke the subkey with the index @key_index. Optionally      return gpg_editkey (this->ctx, this->key, this);
528     a reason can be provided in @reason with a text to describe  }
529     more details in @cmt.  
530     Return value: 0 on success. */  
531  gpgme_error_t  /* Sign a single user-id with the index @_uid_index.
532  GpgKeyEdit::revokeSubkey (int key_index, int reason, const char *cmt)     All other parameters are equal to signKey().
533  {     Return value: 0 on success. */
534      if (!this->key || !this->pass)  gpgme_error_t
535          return gpg_error (GPG_ERR_INV_OBJ);  GpgKeyEdit::signUserid (int _uid_idx, int mode, int _sig_class,
536                            const char *_exp_date)
537      type = GPG_EDITKEY_REVKEY;  {
538      this->key_index = key_index;      if (!this->key)
539      this->reason = reason;          return gpg_error (GPG_ERR_INV_OBJ);
540      free_if_alloc (this->cmt);      if (key_has_passwd && !this->pass)
541      this->cmt = m_strdup (cmt);          return gpg_error (GPG_ERR_INV_PASSPHRASE);
542      return gpg_editkey (this->ctx, this->key, this);  
543  }      this->uid_index = _uid_idx;
544        type = mode;
545        this->exp_date = _exp_date;
546  /* Revoke an entire key. With the reason given in @reason      this->sig_class = _sig_class;
547     and the description in @cmt.      return gpg_editkey (this->ctx, this->key, this);
548     Return value: 0 on success. */  }
549  gpgme_error_t  
550  GpgKeyEdit::revokeKey (int reason, const char *cmt)  
551  {  /* Set the ownertrust of the key stored in the object
552      if (!this->key || !this->pass)     to the trust value @trust.
553          return gpg_error (GPG_ERR_INV_OBJ);     Return value: 0 on success. */
554    gpgme_error_t
555      type = GPG_EDITKEY_REVOKE;  GpgKeyEdit::setTrust (gpgme_validity_t trust)
556      this->reason = reason;  {
557      free_if_alloc (this->cmt);      if (!this->key)
558      this->cmt = m_strdup (cmt);          return gpg_error (GPG_ERR_INV_OBJ);
559      return gpg_editkey (this->ctx, this->key, this);  
560  }      type = GPG_EDITKEY_TRUST;
561        this->trust_id = (int)trust;
562        return gpg_editkey (this->ctx, this->key, this);
563  /* Add a designated revoker to the key. @uid stores  }
564     the user-ID of the key who is allowed to be a  
565     designated revoker.  /* Add a user ID to the given key with the @name as the
566     Return value: 0 on success. */     name, @cmt as the comment (or NULL) and @email as the email.
567  gpgme_error_t     Return value: 0 on success. */
568  GpgKeyEdit::addDesignatedRevoker (const char *uid)  gpgme_error_t
569  {  GpgKeyEdit::addUserid (const char *_name, const char *_cmt, const char *_email)
570      if (!this->key || !this->pass)  {
571          return gpg_error (GPG_ERR_INV_OBJ);      if (!this->key)
572            return gpg_error (GPG_ERR_INV_OBJ);
573      type = GPG_EDITKEY_ADDREV;      if (key_has_passwd && !this->pass)
574      free_if_alloc (this->name);          return gpg_error (GPG_ERR_INV_PASSPHRASE);
575      this->name = m_strdup (uid);  
576      return gpg_editkey (this->ctx, this->key, this);      type = GPG_EDITKEY_ADDUID;
577  }      free_if_alloc (this->name);
578        this->name = m_strdup (_name);
579  /* Add a photo-ID to the key. The JPG image is given      free_if_alloc (this->cmt);
580     in the file with the name @jpg_file.      this->cmt = NULL;
581     Return value: 0 on success. */      if (_cmt != NULL)
582  gpgme_error_t          this->cmt = m_strdup (_cmt);    
583  GpgKeyEdit::addPhotoid (const char *jpg_file)      free_if_alloc (this->email);
584  {      this->email = m_strdup (_email);
585      if (!this->key || !this->pass)      if (!this->email || !this->name)
586          return gpg_error (GPG_ERR_INV_OBJ);          BUG (NULL);
587        return gpg_editkey (this->ctx, this->key, this);
588      type = GPG_EDITKEY_ADDPHOTO;  }
589      this->url = jpg_file;  
590      return gpg_editkey (this->ctx, this->key, this);  /* Delete the user-ID with the index @uid_index of the given key.
591  }     Return value: 0 on success. */
592    gpgme_error_t
593  /* Enable the given key. */  GpgKeyEdit::delUserid (int _uid_index)
594  gpgme_error_t  {
595  GpgKeyEdit::enable (void)      if (!this->key)
596  {          return gpg_error (GPG_ERR_INV_OBJ);
597      if (!this->key)  
598          return gpg_error (GPG_ERR_INV_OBJ);      type = GPG_EDITKEY_DELUID;
599      type = GPG_EDITKEY_ENABLE;      this->uid_index = _uid_index;
600      return gpg_editkey (this->ctx, this->key, this);      return gpg_editkey (this->ctx, this->key, this);
601  }  }
602    
603  /* Disable the given key. */  /* Delete the subkey with the index @key_index.
604  gpgme_error_t     Return value: 0 on success. */
605  GpgKeyEdit::disable (void)  gpgme_error_t
606  {  GpgKeyEdit::delKey (int _key_index)
607      if (!this->key)  {
608          return gpg_error (GPG_ERR_INV_OBJ);      if (!this->key)
609      type = GPG_EDITKEY_DISABLE;          return gpg_error (GPG_ERR_INV_OBJ);
610      return gpg_editkey (this->ctx, this->key, this);  
611  }      type = GPG_EDITKEY_DELKEY;
612        this->key_index = _key_index;
613        return gpg_editkey (this->ctx, this->key, this);
614  /* Update the user-ID preferences of the user-ID with the  }
615     index @uid_index to the prefs given in @new_prefs.  
616     Return value: 0 on success. */  /* Add a new subkey to the given key.
617  gpgme_error_t     The new key will have @pubkey_algo as the algorithm
618  GpgKeyEdit::setUseridPreferences (int uid_index, const char *new_prefs)     and a size of @pubkey_size bits. If valid > 0, the
619  {     key expires in @valid days.
620      if (!this->key || !this->pass)     Return value: 0 on success. */
621          return gpg_error (GPG_ERR_INV_OBJ);  gpgme_error_t
622      return GPG_ERR_NO_ERROR;  GpgKeyEdit::addSubkey (gpgme_pubkey_algo_t _pubkey_algo,
623  }                         unsigned int _pubkey_size, long _valid)
624    {
625        if (!this->key)
626  /* Delete a signature from the user-ID with the index @uid_index.          return gpg_error (GPG_ERR_INV_OBJ);
627     The index of the signature is given in @sig_index.      if (key_has_passwd && !this->pass)
628     Return value: 0 on success. */          return gpg_error (GPG_ERR_INV_PASSPHRASE);
629  gpgme_error_t  
630  GpgKeyEdit::deleteUseridSignature (int uid_index, int sig_index)      type = GPG_EDITKEY_ADDKEY;
631  {      this->pubkey_algo = _pubkey_algo;
632      if (!this->key)      this->pubkey_size = _pubkey_size;
633          return gpg_error (GPG_ERR_INV_OBJ);      this->valid = _valid;
634      type = GPG_EDITKEY_DELSIG;      return gpg_editkey (this->ctx, this->key, this);
635      this->uid_index = uid_index;  }
636      this->sig_index = sig_index;  
637      return gpg_editkey (this->ctx, this->key, this);  /* Change the passphrase of the given key to @new_pass.
638  }     If allow_empty != 0, it is allowed to provide an empty passphrase.
639       Return value: 0 on success. */
640  /* Set the preferred keyserver for the given key to @url.  gpgme_error_t
641     Return value: 0 on success. */  GpgKeyEdit::changePassphrase (const char *_new_pass, int allow_empty)
642  gpgme_error_t  {
643  GpgKeyEdit::setPreferredKeyserver (int uid_index, const char *url)      if (!this->key)
644  {          return gpg_error (GPG_ERR_INV_OBJ);
645      if (!this->key || !this->pass)      if (key_has_passwd && !this->pass)
646          return gpg_error (GPG_ERR_INV_OBJ);          return gpg_error (GPG_ERR_INV_PASSPHRASE);
647      if (!url)      
648          return gpg_error (GPG_ERR_INV_ARG);      type = GPG_EDITKEY_PASSWD;
649      type = GPG_EDITKEY_KEYSERV;      this->new_pass = _new_pass;
650      this->url = url;      this->flags = allow_empty? 1 : 0;
651      this->uid_index = uid_index;      return gpg_editkey (this->ctx, this->key, this);
652      return gpg_editkey (this->ctx, this->key, this);  }
653  }  
654    /* Set the primary user-ID of the given key to user-ID with
655       the index @uid_index.
656       Return value: 0 on success. */
657    gpgme_error_t
658    GpgKeyEdit::setPrimaryUserid (int _uid_index)
659    {
660        if (!this->key)
661            return gpg_error (GPG_ERR_INV_OBJ);
662        if (key_has_passwd && !this->pass)
663            return gpg_error (GPG_ERR_INV_PASSPHRASE);
664    
665        type = GPG_EDITKEY_PRIMARY;
666        this->uid_index = _uid_index;
667        return gpg_editkey (this->ctx, this->key, this);
668    }
669    
670    /* Set the expire date of the subkey with the index @key_index.
671       @exp_timestamp is used to calculate the days the key is valid.
672       if @exp_days is true, exp_timestamp is already converted to days.
673       Return value: 0 on success. */
674    gpgme_error_t
675    GpgKeyEdit::setKeyExpireDate (int _key_index, long exp_timestamp,
676                                  bool exp_days)
677    {
678        if (!this->key)
679            return gpg_error (GPG_ERR_INV_OBJ);
680        if (key_has_passwd && !this->pass)
681            return gpg_error (GPG_ERR_INV_PASSPHRASE);
682        if (!exp_days && exp_timestamp > 0 && exp_timestamp < time (NULL))
683            return gpg_error (GPG_ERR_INV_ARG);
684        
685        type = GPG_EDITKEY_EXPIRE;
686        if (!exp_days && exp_timestamp > 0) {
687            valid = exp_timestamp - time (NULL);
688            valid /= 86400;
689        }
690        else
691            valid = exp_timestamp;
692        this->key_index = _key_index;
693        return gpg_editkey (this->ctx, this->key, this);
694    }
695    
696    /* Revoke the userid given by the index @uid_index.
697       Return value: 0 on success. */
698    gpgme_error_t
699    GpgKeyEdit::revokeUserid (int _uid_index)
700    {
701        if (!this->key)
702            return gpg_error (GPG_ERR_INV_OBJ);
703        if (key_has_passwd && !this->pass)
704            return gpg_error (GPG_ERR_INV_PASSPHRASE);
705    
706        type = GPG_EDITKEY_REVUID;
707        this->uid_index = _uid_index;
708        return gpg_editkey (this->ctx, this->key, this);
709    }
710    
711    
712    /* Revoke a signature on the user-ID with the index @uid_index
713       and the signature index @sig_index.
714       Return value: 0 on success. */
715    gpgme_error_t
716    GpgKeyEdit::revokeSignature (int _uid_index, int _sig_index)
717    {
718        if (!this->key)
719            return gpg_error (GPG_ERR_INV_OBJ);
720        if (key_has_passwd && !this->pass)
721            return gpg_error (GPG_ERR_INV_PASSPHRASE);
722    
723        type = GPG_EDITKEY_REVSIG;
724        this->uid_index = _uid_index;
725        this->sig_index = _sig_index;
726        return gpg_editkey (this->ctx, this->key, this);
727    }
728    
729    
730    /* Revoke the subkey with the index @key_index. Optionally
731       a reason can be provided in @reason with a text to describe
732       more details in @cmt.
733       Return value: 0 on success. */
734    gpgme_error_t
735    GpgKeyEdit::revokeSubkey (int _key_index, int _reason, const char *_cmt)
736    {
737        if (!this->key)
738            return gpg_error (GPG_ERR_INV_OBJ);
739        if (key_has_passwd && !this->pass)
740            return gpg_error (GPG_ERR_INV_PASSPHRASE);
741    
742        type = GPG_EDITKEY_REVKEY;
743        this->key_index = _key_index;
744        this->reason = _reason;
745        free_if_alloc (this->cmt);
746        this->cmt = NULL;
747        if (_cmt)
748            this->cmt = m_strdup (_cmt);
749        return gpg_editkey (this->ctx, this->key, this);
750    }
751    
752    
753    /* Add a designated revoker to the key. @uid stores
754       the user-ID of the key who is allowed to be a
755       designated revoker.
756       Return value: 0 on success. */
757    gpgme_error_t
758    GpgKeyEdit::addDesignatedRevoker (const char *uid)
759    {
760        if (!this->key)
761            return gpg_error (GPG_ERR_INV_OBJ);
762        if (key_has_passwd && !this->pass)
763            return gpg_error (GPG_ERR_INV_PASSPHRASE);
764    
765        type = GPG_EDITKEY_ADDREV;
766        free_if_alloc (this->name);
767        this->name = m_strdup (uid);
768        return gpg_editkey (this->ctx, this->key, this);
769    }
770    
771    /* Add a photo-ID to the key. The JPG image is given
772       in the file with the name @jpg_file.
773       Return value: 0 on success. */
774    gpgme_error_t
775    GpgKeyEdit::addPhotoid (const char *jpg_file)
776    {
777        if (!this->key)
778            return gpg_error (GPG_ERR_INV_OBJ);
779        if (key_has_passwd && !this->pass)
780            return gpg_error (GPG_ERR_INV_PASSPHRASE);
781    
782        type = GPG_EDITKEY_ADDPHOTO;
783        this->url = jpg_file;
784        return gpg_editkey (this->ctx, this->key, this);
785    }
786    
787    /* Enable the given key. */
788    gpgme_error_t
789    GpgKeyEdit::enable (void)
790    {
791        if (!this->key)
792            return gpg_error (GPG_ERR_INV_OBJ);
793        type = GPG_EDITKEY_ENABLE;
794        return gpg_editkey (this->ctx, this->key, this);
795    }
796    
797    /* Disable the given key. */
798    gpgme_error_t
799    GpgKeyEdit::disable (void)
800    {
801        if (!this->key)
802            return gpg_error (GPG_ERR_INV_OBJ);
803        type = GPG_EDITKEY_DISABLE;
804        return gpg_editkey (this->ctx, this->key, this);
805    }
806    
807    
808    /* Remove unusable parts and all signatures from a key. */
809    gpgme_error_t
810    GpgKeyEdit::minimizeKey (void)
811    {
812        if (!this->key)
813            return gpg_error (GPG_ERR_INV_OBJ);
814        type = GPG_EDITKEY_MINIMIZE;
815        return gpg_editkey (this->ctx, this->key, this);
816    }
817    
818    
819    /* Remove unusable parts from a key. */
820    gpgme_error_t
821    GpgKeyEdit::cleanKey (void)
822    {
823        if (!this->key)
824            return gpg_error (GPG_ERR_INV_OBJ);
825        type = GPG_EDITKEY_CLEAN;
826        return gpg_editkey (this->ctx, this->key, this);
827    }
828    
829    
830    /* Update the user-ID preferences of the user-ID with the
831       index @uid_index to the prefs given in @new_prefs.
832       Return value: 0 on success. */
833    gpgme_error_t
834    GpgKeyEdit::setUseridPreferences (int _uid_index, const char *_new_prefs)
835    {
836        if (!this->key)
837            return gpg_error (GPG_ERR_INV_OBJ);
838        if (key_has_passwd && !this->pass)
839            return gpg_error (GPG_ERR_INV_PASSPHRASE);
840        type = GPG_EDITKEY_SETPREF;
841        this->uid_index = _uid_index;
842        this->new_prefs = _new_prefs;
843        return gpg_editkey (this->ctx, this->key, this);
844    }
845    
846    
847    /* Delete a signature from the user-ID with the index @uid_index.
848       The index of the signature is given in @sig_index.
849       Return value: 0 on success. */
850    gpgme_error_t
851    GpgKeyEdit::delUseridSignature (int _uid_index, int _sig_index)
852    {
853        if (!this->key)
854            return gpg_error (GPG_ERR_INV_OBJ);
855        type = GPG_EDITKEY_DELSIG;
856        this->uid_index = _uid_index;
857        this->sig_index = _sig_index;
858        return gpg_editkey (this->ctx, this->key, this);
859    }
860    
861    /* Set the preferred keyserver for the given key to @url.
862       If @_uid_index is -1, set the keyserver for all user-ids.
863       Return value: 0 on success. */
864    gpgme_error_t
865    GpgKeyEdit::setPreferredKeyserver (int _uid_index, const char *_url)
866    {
867        if (!this->key)
868            return gpg_error (GPG_ERR_INV_OBJ);
869        if (key_has_passwd && !this->pass)
870            return gpg_error (GPG_ERR_INV_PASSPHRASE);
871        if (!_url)
872            return gpg_error (GPG_ERR_INV_ARG);
873    
874        type = GPG_EDITKEY_KEYSERV;
875        this->url = _url;
876        this->uid_index = _uid_index;
877        return gpg_editkey (this->ctx, this->key, this);
878    }
879    
880    
881    /* Return the saved user-id index. */
882    int
883    GpgKeyEdit::getUseridIndex (void)
884    {
885        return uid_index;
886    }
887    
888    
889    /* Return the saved key index. */  
890    int
891    GpgKeyEdit::getKeyIndex (void)
892    {
893        return key_index;
894    }
895    
896    
897    /* Return the saved sig index. */
898    int
899    GpgKeyEdit::getSigIndex (void)
900    {
901        return sig_index;
902    }

Legend:
Removed from v.23  
changed lines
  Added in v.234

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26