certmanager/lib

kpgpkeylistjob.cpp
1 /*
2  kpgpkeylistjob.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org>
6 
7  Libkleopatra is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11 
12  Libkleopatra 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 this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the TQt library by Trolltech AS, Norway (or with modified versions
24  of TQt that use the same license as TQt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  TQt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include "kpgpkeylistjob.h"
38 
39 #include <kpgpbase.h>
40 #include <kpgpkey.h>
41 
42 #include <gpgmepp/key.h>
43 #include <gpgmepp/keylistresult.h>
44 
45 #include <gpgme.h>
46 
47 #include <tqtimer.h>
48 
49 #include <stdlib.h>
50 #include <string.h>
51 #include <assert.h>
52 
53 Kleo::KpgpKeyListJob::KpgpKeyListJob( Kpgp::Base * pgpBase )
54  : KeyListJob( 0, "Kleo::KpgpKeyListJob" ),
55  mPgpBase( pgpBase )
56 {
57 }
58 
59 Kleo::KpgpKeyListJob::~KpgpKeyListJob() {
60 }
61 
62 // the following function is a verbatim copy from gpgme/key.c
63 static char *
64 set_user_id_part (char *tail, const char *buf, size_t len)
65 {
66  while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
67  len--;
68  for (; len; len--)
69  *tail++ = *buf++;
70  *tail++ = 0;
71  return tail;
72 }
73 
74 // the following function is a verbatim copy from gpgme/key.c
75 static void
76 parse_user_id (char *src, char **name, char **email,
77  char **comment, char *tail)
78 {
79  const char *start = NULL;
80  int in_name = 0;
81  int in_email = 0;
82  int in_comment = 0;
83 
84  while (*src)
85  {
86  if (in_email)
87  {
88  if (*src == '<')
89  /* Not legal but anyway. */
90  in_email++;
91  else if (*src == '>')
92  {
93  if (!--in_email && !*email)
94  {
95  *email = tail;
96  tail = set_user_id_part (tail, start, src - start);
97  }
98  }
99  }
100  else if (in_comment)
101  {
102  if (*src == '(')
103  in_comment++;
104  else if (*src == ')')
105  {
106  if (!--in_comment && !*comment)
107  {
108  *comment = tail;
109  tail = set_user_id_part (tail, start, src - start);
110  }
111  }
112  }
113  else if (*src == '<')
114  {
115  if (in_name)
116  {
117  if (!*name)
118  {
119  *name = tail;
120  tail = set_user_id_part (tail, start, src - start);
121  }
122  in_name = 0;
123  }
124  in_email = 1;
125  start = src + 1;
126  }
127  else if (*src == '(')
128  {
129  if (in_name)
130  {
131  if (!*name)
132  {
133  *name = tail;
134  tail = set_user_id_part (tail, start, src - start);
135  }
136  in_name = 0;
137  }
138  in_comment = 1;
139  start = src + 1;
140  }
141  else if (!in_name && *src != ' ' && *src != '\t')
142  {
143  in_name = 1;
144  start = src;
145  }
146  src++;
147  }
148 
149  if (in_name)
150  {
151  if (!*name)
152  {
153  *name = tail;
154  tail = set_user_id_part (tail, start, src - start);
155  }
156  }
157 
158  /* Let unused parts point to an EOS. */
159  tail--;
160  if (!*name)
161  *name = tail;
162  if (!*email)
163  *email = tail;
164  if (!*comment)
165  *comment = tail;
166 }
167 
168 gpgme_user_id_t KpgpUserID2GPGMEUserID( const Kpgp::UserID * kUserId )
169 {
170  // inspired by _gpgme_key_append_name
171 
172  const TQCString text = kUserId->text().utf8();
173  const int src_len = text.length();
174 
175  gpgme_user_id_t uid;
176  /* Allocate enough memory for the _gpgme_user_id struct, for the actual user
177  id (the text) and for the parsed version. */
178  uid = (gpgme_user_id_t) malloc( sizeof( *uid ) + 2 * src_len + 3 );
179  memset( uid, 0, sizeof *uid );
180  uid->revoked = kUserId->revoked();
181  uid->invalid = kUserId->invalid();
182  uid->validity = (gpgme_validity_t) kUserId->validity();
183 
184  uid->uid = ((char *) uid) + sizeof (*uid);
185  char *dst = uid->uid;
186  memcpy( dst, text.data(), src_len + 1 );
187 
188  dst += src_len + 1;
189  parse_user_id( uid->uid, &uid->name, &uid->email,
190  &uid->comment, dst );
191 
192  return uid;
193 }
194 
195 gpgme_subkey_t KpgpSubkey2GPGMESubKey( const Kpgp::Subkey * kSubkey )
196 {
197  gpgme_subkey_t subkey;
198 
199  const TQCString fpr = kSubkey->fingerprint();
200  const unsigned int fpr_len = fpr.length();
201  const TQCString keyId = kSubkey->longKeyID();
202 
203  subkey = (gpgme_subkey_t) calloc( 1, sizeof( *subkey ) + fpr_len + 1 );
204  subkey->revoked = kSubkey->revoked();
205  subkey->expired = kSubkey->expired();
206  subkey->disabled = kSubkey->disabled();
207  subkey->invalid = kSubkey->invalid();
208  subkey->can_encrypt = kSubkey->canEncrypt();
209  subkey->can_sign = kSubkey->canSign();
210  subkey->can_certify = kSubkey->canCertify();
211  subkey->secret = kSubkey->secret();
212  subkey->pubkey_algo = (gpgme_pubkey_algo_t) kSubkey->keyAlgorithm();
213  subkey->length = kSubkey->keyLength();
214  subkey->keyid = subkey->_keyid;
215  memcpy( subkey->_keyid, keyId.data(), keyId.length() + 1 );
216  subkey->fpr = ((char *) subkey) + sizeof( *subkey );
217  memcpy( subkey->fpr, fpr.data(), fpr_len + 1 );
218  subkey->timestamp = kSubkey->creationDate();
219  subkey->expires = kSubkey->expirationDate();
220 
221  return subkey;
222 }
223 
224 gpgme_key_t KpgpKey2gpgme_key( const Kpgp::Key * kKey )
225 {
226  gpgme_key_t key;
227 
228  key = (gpgme_key_t) calloc( 1, sizeof( *key ) );
229  key->revoked = kKey->revoked();
230  key->expired = kKey->expired();
231  key->disabled = kKey->disabled();
232  key->invalid = kKey->invalid();
233  key->can_encrypt = kKey->canEncrypt();
234  key->can_sign = kKey->canSign();
235  key->can_certify = kKey->canCertify();
236  key->secret = kKey->secret();
237  key->protocol = GPGME_PROTOCOL_OpenPGP;
238  key->owner_trust = GPGME_VALIDITY_UNKNOWN; // FIXME?
239 
240  Kpgp::UserIDList kUserIDs = kKey->userIDs();
241  for ( Kpgp::UserIDListIterator it( kUserIDs ); it.current(); ++it ) {
242  gpgme_user_id_t uid = KpgpUserID2GPGMEUserID( *it );
243  if ( !key->uids )
244  key->uids = uid;
245  if ( key->_last_uid )
246  key->_last_uid->next = uid;
247  key->_last_uid = uid;
248  }
249 
250  Kpgp::SubkeyList kSubkeys = kKey->subkeys();
251  for ( Kpgp::SubkeyListIterator it( kSubkeys ); it.current(); ++it ) {
252  gpgme_subkey_t subkey = KpgpSubkey2GPGMESubKey( *it );
253  if (!key->subkeys)
254  key->subkeys = subkey;
255  if (key->_last_subkey)
256  key->_last_subkey->next = subkey;
257  key->_last_subkey = subkey;
258  }
259 
260  return key;
261 }
262 
263 GpgME::Error Kleo::KpgpKeyListJob::start( const TQStringList & patterns,
264  bool secretOnly ) {
265  mPatterns = patterns;
266  mSecretOnly = secretOnly;
267  TQTimer::singleShot( 0, this, TQ_SLOT( slotDoIt() ) );
268  return GpgME::Error( 0 );
269 }
270 
271 void Kleo::KpgpKeyListJob::slotDoIt() {
272  std::vector<GpgME::Key> keys;
273  GpgME::KeyListResult res = exec( mPatterns, mSecretOnly, keys );
274  for ( std::vector<GpgME::Key>::const_iterator it = keys.begin();
275  it != keys.end(); ++it )
276  emit nextKey( *it );
277  emit done();
278  emit result( res );
279  deleteLater();
280 }
281 
282 GpgME::KeyListResult Kleo::KpgpKeyListJob::exec( const TQStringList & patterns,
283  bool secretOnly,
284  std::vector<GpgME::Key> & keys ) {
285  Kpgp::KeyList kKeys;
286  if ( secretOnly )
287  kKeys = mPgpBase->secretKeys( patterns );
288  else
289  kKeys = mPgpBase->publicKeys( patterns );
290 
291  keys.clear();
292  for ( Kpgp::KeyListIterator it( kKeys ); it.current(); ++it ) {
293  keys.push_back( GpgME::Key( KpgpKey2gpgme_key(*it), true ) );
294  }
295 
296  _gpgme_op_keylist_result res;
297  res.truncated = 0; // key list is not truncated
298  res._unused = 0;
299 
300  return GpgME::KeyListResult( GpgME::Error( 0 ), res );
301 }
302 
303 #include "kpgpkeylistjob.moc"