1 |
twoaday |
17 |
/* key.c - Key objects |
2 |
twoaday |
2 |
* Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH |
3 |
twoaday |
17 |
* Copyright (C) 2001-2005 Timo Schulz |
4 |
twoaday |
2 |
* |
5 |
|
|
* This file is part of MyGPGME. |
6 |
|
|
* |
7 |
|
|
* MyGPGME is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* MyGPGME 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 |
15 |
|
|
* GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <string.h> |
24 |
|
|
#include <stdlib.h> |
25 |
|
|
#include <assert.h> |
26 |
|
|
#include <time.h> |
27 |
|
|
#include <ctype.h> |
28 |
|
|
|
29 |
|
|
#include "util.h" |
30 |
|
|
#include "ops.h" |
31 |
|
|
#include "key.h" |
32 |
|
|
|
33 |
|
|
static const char * |
34 |
twoaday |
17 |
pkalgo_to_string (int algo) |
35 |
twoaday |
2 |
{ |
36 |
twoaday |
17 |
switch (algo) { |
37 |
twoaday |
2 |
case 0: |
38 |
|
|
case 1: |
39 |
|
|
case 2: |
40 |
twoaday |
17 |
case 3: return "RSA"; |
41 |
twoaday |
2 |
case 17: return "DSA"; |
42 |
twoaday |
22 |
case 16: |
43 |
twoaday |
17 |
case 20: return "ELG"; |
44 |
|
|
default: return "???"; |
45 |
twoaday |
2 |
} |
46 |
|
|
} /* pkalgo_to_string */ |
47 |
|
|
|
48 |
twoaday |
17 |
|
49 |
twoaday |
2 |
static gpgme_error_t |
50 |
twoaday |
17 |
key_new (gpgme_key_t *r_key, int secret) |
51 |
twoaday |
2 |
{ |
52 |
|
|
gpgme_key_t key; |
53 |
|
|
|
54 |
twoaday |
17 |
if (r_key) |
55 |
twoaday |
2 |
*r_key = NULL; |
56 |
twoaday |
17 |
key = calloc (1, sizeof *key); |
57 |
twoaday |
2 |
if (!key) |
58 |
|
|
return mk_error (Out_Of_Core); |
59 |
|
|
key->ref_count = 1; |
60 |
|
|
if( r_key ) |
61 |
|
|
*r_key = key; |
62 |
|
|
if( secret ) |
63 |
|
|
key->secret = 1; |
64 |
|
|
|
65 |
|
|
return 0; |
66 |
|
|
} /* key_new */ |
67 |
|
|
|
68 |
|
|
|
69 |
|
|
gpgme_error_t |
70 |
|
|
_gpgme_key_new( gpgme_key_t *r_key ) |
71 |
|
|
{ |
72 |
|
|
return key_new( r_key, 0 ); |
73 |
|
|
} /* _gpgme_key_new */ |
74 |
|
|
|
75 |
|
|
|
76 |
|
|
gpgme_error_t |
77 |
|
|
_gpgme_key_new_secret( gpgme_key_t *r_key ) |
78 |
|
|
{ |
79 |
|
|
return key_new( r_key, 1 ); |
80 |
|
|
} /* _gpgme_key_new_secret */ |
81 |
|
|
|
82 |
|
|
|
83 |
|
|
void |
84 |
|
|
gpgme_key_ref( gpgme_key_t key ) |
85 |
|
|
{ |
86 |
|
|
return_if_fail( key ); |
87 |
|
|
key->ref_count++; |
88 |
|
|
} /* gpgme_key_ref */ |
89 |
|
|
|
90 |
|
|
|
91 |
|
|
static struct subkey_s * |
92 |
|
|
add_subkey( gpgme_key_t key, int secret ) |
93 |
|
|
{ |
94 |
|
|
struct subkey_s *k, *kk; |
95 |
|
|
|
96 |
|
|
k = calloc (1, sizeof *k); |
97 |
|
|
if( !k ) |
98 |
|
|
return NULL; |
99 |
|
|
|
100 |
|
|
kk = key->keys.next; |
101 |
|
|
if( !kk ) |
102 |
|
|
key->keys.next = k; |
103 |
|
|
else { |
104 |
|
|
while ( kk->next ) |
105 |
|
|
kk = kk->next; |
106 |
|
|
kk->next = k; |
107 |
|
|
} |
108 |
|
|
if( secret ) |
109 |
|
|
k->secret = 1; |
110 |
|
|
return k; |
111 |
|
|
} /* add_subkey */ |
112 |
|
|
|
113 |
|
|
|
114 |
|
|
struct subkey_s * |
115 |
|
|
_gpgme_key_add_subkey( gpgme_key_t key ) |
116 |
|
|
{ |
117 |
|
|
return add_subkey( key, 0 ); |
118 |
|
|
} /* _gpgme_key_add_subkey */ |
119 |
|
|
|
120 |
|
|
|
121 |
|
|
struct subkey_s * |
122 |
|
|
_gpgme_key_add_secret_subkey( gpgme_key_t key ) |
123 |
|
|
{ |
124 |
|
|
return add_subkey( key, 1 ); |
125 |
|
|
} /* _gpgme_key_add_secret_subkey */ |
126 |
|
|
|
127 |
|
|
|
128 |
|
|
struct signature_s * |
129 |
|
|
_gpgme_key_add_signature( gpgme_key_t key ) |
130 |
|
|
{ |
131 |
|
|
struct signature_s *s; |
132 |
|
|
|
133 |
|
|
s = calloc( 1, sizeof *s ); |
134 |
|
|
if( !s ) |
135 |
|
|
return NULL; |
136 |
|
|
s->next = key->sigs; |
137 |
|
|
key->sigs = s; |
138 |
|
|
return s; |
139 |
|
|
} /* _gpgme_key_add_signature */ |
140 |
|
|
|
141 |
|
|
|
142 |
|
|
void |
143 |
|
|
gpgme_key_release( gpgme_key_t key ) |
144 |
|
|
{ |
145 |
|
|
struct user_id_s *u, *u2; |
146 |
|
|
struct subkey_s *k, *k2; |
147 |
|
|
struct revoker_key_s *r, *r2; |
148 |
|
|
struct signature_s *s, *s2; |
149 |
|
|
|
150 |
|
|
if( key == NULL ) |
151 |
|
|
return; |
152 |
|
|
|
153 |
|
|
assert( key->ref_count ); |
154 |
|
|
if( --key->ref_count ) |
155 |
|
|
return; |
156 |
|
|
|
157 |
|
|
safe_free( key->attrib.d ); |
158 |
|
|
safe_free( key->keys.fingerprint ); |
159 |
|
|
for( k = key->keys.next; k; k = k2 ) { |
160 |
|
|
k2 = k->next; |
161 |
|
|
safe_free( k->fingerprint ); |
162 |
|
|
safe_free( k ); |
163 |
|
|
} |
164 |
|
|
for( u = key->uids; u; u = u2 ) { |
165 |
|
|
u2 = u->next; |
166 |
|
|
safe_free (u->hash); |
167 |
|
|
safe_free (u); |
168 |
|
|
} |
169 |
|
|
for( r = key->rvks; r; r = r2 ) { |
170 |
|
|
r2 = r->next; |
171 |
|
|
safe_free( r ); |
172 |
|
|
} |
173 |
|
|
for( s = key->sigs; s; s = s2 ) { |
174 |
|
|
s2 = s->next; |
175 |
|
|
safe_free( s->issuer ); |
176 |
|
|
safe_free( s->user_id ); |
177 |
|
|
safe_free( s ); |
178 |
|
|
} |
179 |
|
|
safe_free( key ); |
180 |
|
|
} /* gpgme_key_release */ |
181 |
|
|
|
182 |
|
|
void |
183 |
|
|
gpgme_key_unref( gpgme_key_t key ) |
184 |
|
|
{ |
185 |
|
|
gpgme_key_release( key ); |
186 |
|
|
} |
187 |
|
|
|
188 |
|
|
|
189 |
|
|
static char * |
190 |
twoaday |
17 |
set_user_id_part (char *tail, const char *buf, size_t len) |
191 |
twoaday |
2 |
{ |
192 |
twoaday |
17 |
while (len && (buf[len-1] == ' ' || buf[len-1] == '\t')) |
193 |
twoaday |
2 |
len--; |
194 |
twoaday |
17 |
for (; len; len--) |
195 |
twoaday |
2 |
*tail++ = *buf++; |
196 |
|
|
*tail++ = 0; |
197 |
|
|
return tail; |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
|
201 |
|
|
static void |
202 |
|
|
parse_user_id( struct user_id_s *uid, char *tail ) |
203 |
|
|
{ |
204 |
|
|
const char *s, *start=NULL; |
205 |
|
|
int in_name = 0; |
206 |
|
|
int in_email = 0; |
207 |
|
|
int in_comment = 0; |
208 |
|
|
|
209 |
|
|
for( s=uid->name; *s; s++ ) { |
210 |
|
|
if ( in_email ) { |
211 |
|
|
if ( *s == '<' ) |
212 |
|
|
in_email++; /* not legal but anyway */ |
213 |
|
|
else if (*s== '>') { |
214 |
|
|
if ( !--in_email ) { |
215 |
|
|
if (!uid->email_part) { |
216 |
|
|
uid->email_part = tail; |
217 |
|
|
tail = set_user_id_part ( tail, start, s-start ); |
218 |
|
|
} |
219 |
|
|
} |
220 |
|
|
} |
221 |
|
|
} |
222 |
|
|
else if( in_comment ) { |
223 |
|
|
if( *s == '(' ) |
224 |
|
|
in_comment++; |
225 |
|
|
else if (*s== ')') { |
226 |
|
|
if ( !--in_comment ) { |
227 |
|
|
if (!uid->comment_part) { |
228 |
|
|
uid->comment_part = tail; |
229 |
|
|
tail = set_user_id_part ( tail, start, s-start ); |
230 |
|
|
} |
231 |
|
|
} |
232 |
|
|
} |
233 |
|
|
} |
234 |
|
|
else if( *s == '<' ) { |
235 |
|
|
if( in_name ) { |
236 |
|
|
if( !uid->name_part ) { |
237 |
|
|
uid->name_part = tail; |
238 |
|
|
tail = set_user_id_part (tail, start, s-start ); |
239 |
|
|
} |
240 |
|
|
in_name = 0; |
241 |
|
|
} |
242 |
|
|
in_email = 1; |
243 |
|
|
start = s+1; |
244 |
|
|
} |
245 |
|
|
else if ( *s == '(' ) { |
246 |
|
|
if ( in_name ) { |
247 |
|
|
if ( !uid->name_part ) { |
248 |
|
|
uid->name_part = tail; |
249 |
|
|
tail = set_user_id_part (tail, start, s-start ); |
250 |
|
|
} |
251 |
|
|
in_name = 0; |
252 |
|
|
} |
253 |
|
|
in_comment = 1; |
254 |
|
|
start = s+1; |
255 |
|
|
} |
256 |
|
|
else if ( !in_name && *s != ' ' && *s != '\t' ) { |
257 |
|
|
in_name = 1; |
258 |
|
|
start = s; |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
if( in_name ) { |
263 |
|
|
if ( !uid->name_part ) { |
264 |
|
|
uid->name_part = tail; |
265 |
|
|
tail = set_user_id_part (tail, start, s-start ); |
266 |
|
|
} |
267 |
|
|
} |
268 |
|
|
|
269 |
|
|
/* let unused parts point to an EOS */ |
270 |
|
|
tail--; |
271 |
|
|
if (!uid->name_part) |
272 |
|
|
uid->name_part = tail; |
273 |
|
|
if (!uid->email_part) |
274 |
|
|
uid->email_part = tail; |
275 |
|
|
if (!uid->comment_part) |
276 |
|
|
uid->comment_part = tail; |
277 |
|
|
|
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
|
281 |
|
|
/* |
282 |
|
|
* Take a name from the --with-colon listing, remove certain escape sequences |
283 |
|
|
* sequences and put it into the list of UIDs |
284 |
|
|
*/ |
285 |
|
|
gpgme_error_t |
286 |
|
|
_gpgme_key_append_name (gpgme_key_t key, const char * s, struct user_id_s ** u) |
287 |
|
|
{ |
288 |
|
|
struct user_id_s *uid, *u1; |
289 |
|
|
char *dst; |
290 |
|
|
|
291 |
|
|
assert( key ); |
292 |
|
|
/* we can malloc a buffer of the same length, because the |
293 |
|
|
* converted string will never be larger. Actually we allocate it |
294 |
|
|
* twice the size, so that we are able to store the parsed stuff |
295 |
|
|
* there too */ |
296 |
|
|
uid = malloc (sizeof *uid + 2*strlen (s)+3); |
297 |
|
|
if (!uid) |
298 |
|
|
return mk_error (Out_Of_Core); |
299 |
|
|
uid->flags.revoked = 0; |
300 |
|
|
uid->flags.invalid = 0; |
301 |
|
|
uid->validity = 0; |
302 |
|
|
uid->name_part = NULL; |
303 |
|
|
uid->email_part = NULL; |
304 |
|
|
uid->comment_part = NULL; |
305 |
|
|
uid->hash = NULL; |
306 |
|
|
uid->next = NULL; |
307 |
|
|
dst = uid->name; |
308 |
|
|
|
309 |
twoaday |
17 |
_gpgme_decode_c_string (s, &dst, strlen (s)+1); |
310 |
|
|
dst += strlen (s) + 1; |
311 |
|
|
parse_user_id (uid, dst); |
312 |
twoaday |
2 |
|
313 |
|
|
if (!key->uids) |
314 |
|
|
key->uids = uid; |
315 |
|
|
else { |
316 |
|
|
for (u1 = key->uids; u1 && u1->next; u1 = u1->next) |
317 |
|
|
; |
318 |
|
|
u1->next = uid; |
319 |
|
|
} |
320 |
|
|
if (u) |
321 |
|
|
*u = uid; |
322 |
|
|
return 0; |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
|
326 |
|
|
static const char * |
327 |
|
|
capabilities_to_string (struct subkey_s *k) |
328 |
|
|
{ |
329 |
|
|
static char *strings[8] = { |
330 |
|
|
"", |
331 |
|
|
"c", |
332 |
|
|
"s", |
333 |
|
|
"sc", |
334 |
|
|
"e", |
335 |
|
|
"ec", |
336 |
|
|
"es", |
337 |
|
|
"esc" |
338 |
|
|
}; |
339 |
twoaday |
17 |
return strings[ (!!k->flags.can_encrypt << 2) |
340 |
twoaday |
2 |
| (!!k->flags.can_sign << 1) |
341 |
twoaday |
17 |
| (!!k->flags.can_certify )]; |
342 |
twoaday |
2 |
} |
343 |
|
|
|
344 |
|
|
const char * |
345 |
twoaday |
17 |
gpgme_key_get_string_attr (gpgme_key_t key, gpgme_attr_t what, |
346 |
|
|
void **reserved, int idx) |
347 |
twoaday |
2 |
{ |
348 |
|
|
const char *val = NULL; |
349 |
|
|
struct subkey_s * k; |
350 |
|
|
struct user_id_s * u; |
351 |
|
|
struct revoker_key_s * r; |
352 |
|
|
struct signature_s * s; |
353 |
|
|
struct mpi_s * m; |
354 |
|
|
|
355 |
|
|
if( !key ) |
356 |
|
|
return NULL; |
357 |
|
|
if( idx < 0 ) |
358 |
|
|
return NULL; |
359 |
|
|
|
360 |
|
|
switch( what ) { |
361 |
|
|
case GPGME_ATTR_KEYID: |
362 |
|
|
for (k=&key->keys; k && idx; k=k->next, idx-- ) |
363 |
|
|
; |
364 |
|
|
if (k) |
365 |
|
|
val = k->keyid; |
366 |
|
|
break; |
367 |
|
|
case GPGME_ATTR_FPR: |
368 |
|
|
for (k=&key->keys; k && idx; k=k->next, idx-- ) |
369 |
|
|
; |
370 |
|
|
if (k) |
371 |
|
|
val = k->fingerprint; |
372 |
|
|
break; |
373 |
|
|
case GPGME_ATTR_ALGO: |
374 |
|
|
for (k=&key->keys; k && idx; k=k->next, idx-- ) |
375 |
|
|
; |
376 |
|
|
if (k) |
377 |
|
|
val = pkalgo_to_string (k->key_algo); |
378 |
|
|
break; |
379 |
|
|
case GPGME_ATTR_LEN: |
380 |
|
|
case GPGME_ATTR_CREATED: |
381 |
|
|
case GPGME_ATTR_EXPIRE: |
382 |
|
|
break; /* use another get function */ |
383 |
|
|
case GPGME_ATTR_OTRUST: |
384 |
|
|
val = "[fixme]"; |
385 |
|
|
break; |
386 |
|
|
case GPGME_ATTR_USERID: |
387 |
|
|
for (u=key->uids; u && idx; u=u->next, idx-- ) |
388 |
|
|
; |
389 |
|
|
val = u? u->name : NULL; |
390 |
|
|
break; |
391 |
|
|
case GPGME_ATTR_NAME: |
392 |
|
|
for (u=key->uids; u && idx; u=u->next, idx-- ) |
393 |
|
|
; |
394 |
|
|
val = u? u->name_part : NULL; |
395 |
|
|
break; |
396 |
|
|
case GPGME_ATTR_EMAIL: |
397 |
|
|
for (u=key->uids; u && idx; u=u->next, idx-- ) |
398 |
|
|
; |
399 |
|
|
val = u? u->email_part : NULL; |
400 |
|
|
break; |
401 |
|
|
case GPGME_ATTR_COMMENT: |
402 |
|
|
for( u = key->uids; u && idx; u = u->next, idx-- ) |
403 |
|
|
; |
404 |
|
|
val = u? u->comment_part : NULL; |
405 |
|
|
break; |
406 |
|
|
case GPGME_ATTR_VALIDITY: |
407 |
|
|
for( u = key->uids; u && idx; u = u->next, idx-- ) |
408 |
|
|
; |
409 |
|
|
if( u ) { |
410 |
|
|
switch( u->validity ) { |
411 |
|
|
case GPGME_VALIDITY_UNKNOWN: val = "?"; break; |
412 |
|
|
case GPGME_VALIDITY_UNDEFINED: val = "q"; break; |
413 |
|
|
case GPGME_VALIDITY_NEVER: val = "n"; break; |
414 |
|
|
case GPGME_VALIDITY_MARGINAL: val = "m"; break; |
415 |
|
|
case GPGME_VALIDITY_FULL: val = "f"; break; |
416 |
|
|
case GPGME_VALIDITY_ULTIMATE: val = "u"; break; |
417 |
|
|
} |
418 |
|
|
} |
419 |
|
|
break; |
420 |
|
|
|
421 |
|
|
case GPGME_ATTR_LEVEL: /* not used here */ |
422 |
|
|
case GPGME_ATTR_TYPE: |
423 |
|
|
case GPGME_ATTR_KEY_REVOKED: |
424 |
|
|
case GPGME_ATTR_KEY_INVALID: |
425 |
|
|
case GPGME_ATTR_UID_REVOKED: |
426 |
|
|
case GPGME_ATTR_UID_INVALID: |
427 |
|
|
case GPGME_ATTR_CAN_ENCRYPT: |
428 |
|
|
case GPGME_ATTR_CAN_SIGN: |
429 |
|
|
case GPGME_ATTR_CAN_CERTIFY: |
430 |
|
|
break; |
431 |
|
|
|
432 |
|
|
case GPGME_ATTR_UID_HASH: |
433 |
|
|
for (u=key->uids; u && idx; u=u->next, idx--) |
434 |
|
|
; |
435 |
|
|
if (u) |
436 |
|
|
val = u->hash; |
437 |
|
|
break; |
438 |
|
|
|
439 |
|
|
case GPGME_ATTR_IS_SECRET: |
440 |
|
|
if( key->secret ) |
441 |
|
|
val = "1"; |
442 |
|
|
break; |
443 |
|
|
|
444 |
|
|
case GPGME_ATTR_IS_ULTIMATE: |
445 |
|
|
if( key->gloflags.ultimate ) |
446 |
|
|
val = "1"; |
447 |
|
|
break; |
448 |
|
|
|
449 |
|
|
case GPGME_ATTR_KEY_CAPS: |
450 |
|
|
for( k = &key->keys; k && idx; k = k->next, idx-- ) |
451 |
|
|
; |
452 |
|
|
if( k ) |
453 |
|
|
val = capabilities_to_string( k ); |
454 |
|
|
break; |
455 |
|
|
|
456 |
|
|
case GPGME_ATTR_REVKEY_FPR: |
457 |
|
|
for( r = key->rvks; r && idx; r = r->next, idx-- ) |
458 |
|
|
; |
459 |
|
|
if( r ) |
460 |
|
|
val = r->fpr; |
461 |
|
|
break; |
462 |
|
|
|
463 |
|
|
case GPGME_ATTR_SIG_KEYID: |
464 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
465 |
|
|
; |
466 |
|
|
if( s ) |
467 |
|
|
val = s->keyid; |
468 |
|
|
break; |
469 |
|
|
|
470 |
|
|
case GPGME_ATTR_SIG_ISSUER: |
471 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
472 |
|
|
; |
473 |
|
|
if( s ) |
474 |
|
|
val = s->issuer; |
475 |
|
|
break; |
476 |
|
|
|
477 |
|
|
case GPGME_ATTR_SIG_USERID: |
478 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
479 |
|
|
; |
480 |
|
|
if( s ) |
481 |
|
|
val = s->user_id; |
482 |
|
|
|
483 |
|
|
case GPGME_ATTR_KEYDAT_VAL: |
484 |
|
|
for( m=key->pkey; m && idx; m=m->next, idx-- ) |
485 |
|
|
; |
486 |
twoaday |
17 |
if (m) |
487 |
twoaday |
2 |
val = m->hexval; |
488 |
|
|
break; |
489 |
|
|
|
490 |
|
|
case GPGME_ATTR_PHOTO: |
491 |
|
|
if( key->attrib.used ) |
492 |
|
|
val = key->attrib.d; |
493 |
|
|
if( reserved ) |
494 |
|
|
*reserved = (size_t *)key->attrib.len; |
495 |
|
|
break; |
496 |
|
|
|
497 |
|
|
case GPGME_ATTR_KEY_SYMPREFS: |
498 |
|
|
if( key->sym_prefs ) |
499 |
|
|
val = key->sym_prefs; |
500 |
|
|
break; |
501 |
|
|
|
502 |
|
|
case GPGME_ATTR_KEY_CARDNO: |
503 |
|
|
for( k=&key->keys; k && idx; k=k->next, idx-- ) |
504 |
|
|
; |
505 |
|
|
if (k) |
506 |
|
|
val = k->cardno; |
507 |
|
|
break; |
508 |
|
|
} |
509 |
|
|
return val; |
510 |
|
|
} |
511 |
|
|
|
512 |
|
|
|
513 |
|
|
unsigned long |
514 |
twoaday |
21 |
gpgme_key_get_ulong_attr (gpgme_key_t key, gpgme_attr_t what, |
515 |
twoaday |
22 |
void **reserved, int idx) |
516 |
twoaday |
2 |
{ |
517 |
|
|
unsigned long val = 0; |
518 |
|
|
struct subkey_s * k; |
519 |
|
|
struct user_id_s * u; |
520 |
|
|
struct revoker_key_s * r; |
521 |
|
|
struct signature_s * s; |
522 |
|
|
struct mpi_s * m; |
523 |
|
|
int n=0; |
524 |
|
|
|
525 |
twoaday |
22 |
if (!key || idx < 0) |
526 |
twoaday |
2 |
return 0; |
527 |
|
|
|
528 |
|
|
switch( what ) { |
529 |
|
|
case GPGME_ATTR_ALGO: |
530 |
twoaday |
22 |
for (k=&key->keys; k && idx; k=k->next, idx--) |
531 |
twoaday |
2 |
; |
532 |
|
|
if (k) |
533 |
|
|
val = (unsigned long)k->key_algo; |
534 |
|
|
break; |
535 |
twoaday |
22 |
|
536 |
twoaday |
2 |
case GPGME_ATTR_LEN: |
537 |
twoaday |
22 |
for (k=&key->keys; k && idx; k=k->next, idx--) |
538 |
twoaday |
2 |
; |
539 |
|
|
if (k) |
540 |
|
|
val = (unsigned long)k->key_len; |
541 |
|
|
break; |
542 |
|
|
case GPGME_ATTR_CREATED: |
543 |
|
|
for (k=&key->keys; k && idx; k=k->next, idx-- ) |
544 |
|
|
; |
545 |
|
|
if (k) |
546 |
|
|
val = k->timestamp < 0? 0L:(unsigned long)k->timestamp; |
547 |
|
|
break; |
548 |
|
|
case GPGME_ATTR_VALIDITY: |
549 |
|
|
for (u = key->uids; u && idx; u=u->next, idx--) |
550 |
|
|
; |
551 |
|
|
if (u) |
552 |
|
|
val = u->validity; |
553 |
|
|
break; |
554 |
|
|
|
555 |
|
|
case GPGME_ATTR_IS_SECRET: |
556 |
|
|
val = !!key->secret; |
557 |
|
|
break; |
558 |
|
|
|
559 |
|
|
case GPGME_ATTR_IS_PROTECTED: |
560 |
|
|
val = key->gloflags.is_protected; |
561 |
|
|
break; |
562 |
|
|
|
563 |
|
|
case GPGME_ATTR_IS_ULTIMATE: |
564 |
|
|
val = key->gloflags.ultimate; |
565 |
|
|
break; |
566 |
|
|
|
567 |
|
|
case GPGME_ATTR_KEY_EXPIRED: |
568 |
|
|
for( k = &key->keys; k && idx; k=k->next, idx-- ) |
569 |
|
|
; |
570 |
|
|
if( k ) |
571 |
|
|
val = k->flags.expired; |
572 |
|
|
break; |
573 |
|
|
|
574 |
|
|
case GPGME_ATTR_EXPIRES: |
575 |
|
|
for( k = &key->keys; k && idx; k=k->next, idx-- ) |
576 |
|
|
; |
577 |
|
|
if( k ) |
578 |
|
|
val = k->expires; |
579 |
|
|
break; |
580 |
|
|
|
581 |
|
|
case GPGME_ATTR_KEY_REVOKED: |
582 |
|
|
for( k = &key->keys; k && idx; k=k->next, idx-- ) |
583 |
|
|
; |
584 |
|
|
if( k ) |
585 |
|
|
val = k->flags.revoked; |
586 |
|
|
break; |
587 |
|
|
|
588 |
|
|
case GPGME_ATTR_KEY_INVALID: |
589 |
|
|
for( k = &key->keys; k && idx; k=k->next, idx-- ) |
590 |
|
|
; |
591 |
|
|
if( k ) |
592 |
|
|
val = k->flags.invalid; |
593 |
|
|
break; |
594 |
|
|
|
595 |
|
|
case GPGME_ATTR_UID_CREATED: |
596 |
|
|
for (u=key->uids; u && idx; u=u->next, idx--) |
597 |
|
|
; |
598 |
|
|
if (u) |
599 |
|
|
val = u->created; |
600 |
|
|
break; |
601 |
|
|
|
602 |
|
|
case GPGME_ATTR_UID_REVOKED: |
603 |
|
|
for( u = key->uids; u && idx; u=u->next, idx-- ) |
604 |
|
|
; |
605 |
|
|
if( u ) |
606 |
|
|
val = u->flags.revoked; |
607 |
|
|
break; |
608 |
|
|
|
609 |
|
|
case GPGME_ATTR_UID_INVALID: |
610 |
|
|
for( u =key->uids; u && idx; u=u->next, idx-- ) |
611 |
|
|
; |
612 |
|
|
if( u ) |
613 |
|
|
val = u->flags.invalid; |
614 |
|
|
break; |
615 |
|
|
case GPGME_ATTR_CAN_ENCRYPT: |
616 |
|
|
val = key->gloflags.can_encrypt; |
617 |
|
|
break; |
618 |
|
|
|
619 |
|
|
case GPGME_ATTR_CAN_SIGN: |
620 |
|
|
val = key->gloflags.can_sign; |
621 |
|
|
break; |
622 |
|
|
|
623 |
|
|
case GPGME_ATTR_CAN_CERTIFY: |
624 |
|
|
val = key->gloflags.can_certify; |
625 |
|
|
break; |
626 |
|
|
|
627 |
|
|
case GPGME_ATTR_CAN_AUTH: |
628 |
|
|
val = key->gloflags.can_auth; |
629 |
|
|
break; |
630 |
|
|
|
631 |
|
|
case GPGME_ATTR_DIVERT_CARD: |
632 |
|
|
val = key->gloflags.divert_to_card; |
633 |
|
|
break; |
634 |
|
|
|
635 |
|
|
case GPGME_ATTR_OTRUST: |
636 |
|
|
val = key->otrust; |
637 |
|
|
break; |
638 |
|
|
|
639 |
|
|
case GPGME_ATTR_KEY_VALIDITY: |
640 |
|
|
val = key->validity; |
641 |
|
|
break; |
642 |
|
|
|
643 |
|
|
case GPGME_ATTR_REVKEY_ALGO: |
644 |
|
|
for( r = key->rvks; r && idx; r = r->next, idx-- ) |
645 |
|
|
; |
646 |
|
|
if( r ) |
647 |
|
|
val = r->algo; |
648 |
|
|
break; |
649 |
|
|
|
650 |
|
|
case GPGME_ATTR_SIG_ALGO: |
651 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
652 |
|
|
; |
653 |
|
|
if( s ) |
654 |
|
|
val = s->algo; |
655 |
|
|
break; |
656 |
|
|
|
657 |
|
|
case GPGME_ATTR_SIG_CREATED: |
658 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
659 |
|
|
; |
660 |
|
|
if( s ) |
661 |
|
|
val = s->created; |
662 |
|
|
break; |
663 |
|
|
|
664 |
|
|
case GPGME_ATTR_SIG_EXPIRES: |
665 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
666 |
|
|
; |
667 |
|
|
if( s ) |
668 |
|
|
val = s->expires; |
669 |
|
|
break; |
670 |
|
|
|
671 |
|
|
case GPGME_ATTR_SIG_CLASS: |
672 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
673 |
|
|
; |
674 |
|
|
if( s ) |
675 |
|
|
val = s->sigclass; |
676 |
|
|
break; |
677 |
|
|
|
678 |
|
|
case GPGME_ATTR_SIG_FLAGS: |
679 |
|
|
for (s=key->sigs; s && idx; s=s->next, idx--) |
680 |
|
|
; |
681 |
|
|
if (s) { |
682 |
|
|
if (s->is_local) |
683 |
|
|
val |= GPGME_SIGF_LOCAL; |
684 |
|
|
if (s->is_nonrev) |
685 |
|
|
val |= GPGME_SIGF_NREV; |
686 |
|
|
} |
687 |
|
|
break; |
688 |
|
|
|
689 |
|
|
case GPGME_ATTR_SIG_STAT: |
690 |
|
|
for( s = key->sigs; s && idx; s = s->next, idx-- ) |
691 |
|
|
; |
692 |
|
|
if( s ) |
693 |
|
|
val = s->stat; |
694 |
|
|
break; |
695 |
|
|
|
696 |
|
|
case GPGME_ATTR_KEYDAT_NP: |
697 |
|
|
for( m = key->pkey; m && idx; m=m->next, idx-- ) |
698 |
|
|
n++; |
699 |
|
|
if( m ) |
700 |
|
|
val = n; |
701 |
|
|
break; |
702 |
|
|
|
703 |
|
|
case GPGME_ATTR_KEYDAT_BITS: |
704 |
|
|
for( m = key->pkey; m && idx; m=m->next, idx-- ) |
705 |
|
|
; |
706 |
|
|
if( m ) |
707 |
|
|
val = m->bits; |
708 |
|
|
break; |
709 |
|
|
|
710 |
|
|
case GPGME_ATTR_KEY_DISABLED: |
711 |
|
|
val = key->gloflags.disabled; |
712 |
|
|
break; |
713 |
|
|
|
714 |
twoaday |
21 |
case GPGME_ATTR_VERSION: { |
715 |
|
|
char *fpr = key->keys.fingerprint; |
716 |
|
|
if (!fpr) |
717 |
|
|
val = 4; |
718 |
|
|
else if (key->keys.key_algo == GPGME_PK_RSA && |
719 |
|
|
strlen (fpr) == 32) |
720 |
|
|
val = 3; |
721 |
|
|
} |
722 |
|
|
break; |
723 |
|
|
|
724 |
twoaday |
2 |
case GPGME_ATTR_KEY_USABLE: |
725 |
twoaday |
17 |
n = 4; |
726 |
twoaday |
2 |
for (k=&key->keys; k && idx; k=k->next, idx--) |
727 |
|
|
; |
728 |
twoaday |
17 |
if (k) { |
729 |
twoaday |
2 |
if (!k->flags.revoked) |
730 |
|
|
n--; |
731 |
|
|
if (!k->flags.expired) |
732 |
|
|
n--; |
733 |
|
|
if (!k->flags.invalid) |
734 |
|
|
n--; |
735 |
twoaday |
17 |
if (!key->gloflags.disabled && !k->flags.disabled) |
736 |
|
|
n--; |
737 |
twoaday |
2 |
} |
738 |
|
|
if (n == 0) |
739 |
|
|
val = 1; |
740 |
|
|
break; |
741 |
|
|
|
742 |
|
|
default: |
743 |
|
|
break; |
744 |
|
|
} |
745 |
|
|
return val; |
746 |
|
|
} |
747 |
|
|
|
748 |
|
|
|
749 |
|
|
const char* |
750 |
twoaday |
17 |
gpgme_key_expand_attr (int what, unsigned long attr) |
751 |
twoaday |
2 |
{ |
752 |
|
|
static char tmpbuf[16+1]; |
753 |
|
|
struct tm *iso_date; |
754 |
|
|
|
755 |
|
|
switch( what ) { |
756 |
|
|
case GPGME_ATTR_ALGO: |
757 |
twoaday |
17 |
return pkalgo_to_string (attr); |
758 |
twoaday |
2 |
|
759 |
|
|
case GPGME_ATTR_ALGO_SHORT: |
760 |
|
|
switch( attr ) { |
761 |
|
|
case 17: return "D"; |
762 |
|
|
case 0: |
763 |
|
|
case 1: |
764 |
|
|
case 2: |
765 |
|
|
case 3: return "R"; |
766 |
|
|
case 20: return "G"; |
767 |
|
|
} |
768 |
twoaday |
7 |
return "?"; |
769 |
twoaday |
2 |
|
770 |
|
|
case GPGME_ATTR_VALIDITY: |
771 |
|
|
switch( attr ) { |
772 |
|
|
case '?': |
773 |
|
|
case GPGME_VALIDITY_UNKNOWN: return "Unknown"; |
774 |
|
|
case 'r': |
775 |
|
|
case GPGME_VALIDITY_REVOKED: return "Revoked"; |
776 |
|
|
case 'q': |
777 |
|
|
case '-': |
778 |
|
|
case GPGME_VALIDITY_UNDEFINED: return "Undefined"; |
779 |
|
|
case 'n': |
780 |
|
|
case GPGME_VALIDITY_NEVER: return "Never"; |
781 |
|
|
case 'm': |
782 |
|
|
case GPGME_VALIDITY_MARGINAL: return "Marginal"; |
783 |
|
|
case 'f': |
784 |
|
|
case GPGME_VALIDITY_FULL: return "Full"; |
785 |
|
|
case 'u': |
786 |
|
|
case GPGME_VALIDITY_ULTIMATE: return "Ultimate"; |
787 |
|
|
} |
788 |
twoaday |
7 |
return "???"; |
789 |
twoaday |
2 |
|
790 |
|
|
case GPGME_ATTR_CREATED: |
791 |
|
|
iso_date = localtime((long*) &attr); |
792 |
|
|
_snprintf( tmpbuf, sizeof tmpbuf -1, "%.04d-%.02d-%.02d", |
793 |
|
|
iso_date->tm_year+1900, |
794 |
|
|
iso_date->tm_mon+1, |
795 |
|
|
iso_date->tm_mday ); |
796 |
|
|
return tmpbuf; |
797 |
|
|
|
798 |
|
|
case GPGME_ATTR_LEN: |
799 |
|
|
sprintf( tmpbuf, "%d", attr ); |
800 |
|
|
return tmpbuf; |
801 |
|
|
|
802 |
|
|
case GPGME_ATTR_KEY_SYMPREFS: |
803 |
|
|
switch (attr) { |
804 |
|
|
case 0: return "PLAINTEXT"; |
805 |
|
|
case 1: return "IDEA"; |
806 |
|
|
case 2: return "3DES"; |
807 |
|
|
case 3: return "CAST5"; |
808 |
|
|
case 4: return "BLOWFISH"; |
809 |
|
|
case 5: return "RESERVED"; |
810 |
|
|
case 6: return "RESERVED"; |
811 |
|
|
case 7: return "AES"; |
812 |
|
|
case 8: return "AES-192"; |
813 |
|
|
case 9: return "AES-256"; |
814 |
|
|
} |
815 |
|
|
break; |
816 |
|
|
} |
817 |
|
|
return NULL; |
818 |
|
|
} /* gpgme_key_expand_attr */ |
819 |
|
|
|
820 |
|
|
|
821 |
|
|
int |
822 |
twoaday |
17 |
gpgme_key_get_cability (gpgme_key_t key, int attr, int keyidx) |
823 |
twoaday |
2 |
{ |
824 |
|
|
struct subkey_s *s; |
825 |
|
|
|
826 |
|
|
if( !key ) |
827 |
|
|
return 0; |
828 |
|
|
|
829 |
|
|
for ( s = &key->keys; s && keyidx; s=s->next, keyidx-- ) |
830 |
|
|
; |
831 |
|
|
if (!s) |
832 |
|
|
return 0; |
833 |
|
|
switch (attr) { |
834 |
|
|
case GPGME_ATTR_CAN_ENCRYPT: |
835 |
|
|
return s->flags.can_encrypt; |
836 |
|
|
|
837 |
|
|
case GPGME_ATTR_CAN_SIGN: |
838 |
|
|
return s->flags.can_sign; |
839 |
|
|
|
840 |
|
|
case GPGME_ATTR_CAN_CERTIFY: |
841 |
|
|
return s->flags.can_certify; |
842 |
|
|
|
843 |
|
|
case GPGME_ATTR_CAN_AUTH: |
844 |
|
|
return s->flags.can_auth; |
845 |
|
|
} |
846 |
|
|
return 0; |
847 |
|
|
} /* gpgme_key_get_cability */ |
848 |
|
|
|
849 |
twoaday |
17 |
|
850 |
twoaday |
2 |
int |
851 |
twoaday |
11 |
gpgme_key_count_items (gpgme_key_t key, int what) |
852 |
twoaday |
2 |
{ |
853 |
|
|
union { |
854 |
|
|
struct user_id_s *u; |
855 |
|
|
struct subkey_s *k; |
856 |
|
|
struct revoker_key_s *r; |
857 |
|
|
struct signature_s *s; |
858 |
|
|
} dat; |
859 |
|
|
int count = 0; |
860 |
|
|
|
861 |
twoaday |
17 |
if (!key) |
862 |
twoaday |
2 |
return 0; |
863 |
|
|
switch( what ) { |
864 |
|
|
case GPGME_ATTR_USERID: |
865 |
|
|
for( dat.u = key->uids; dat.u; dat.u = dat.u->next ) |
866 |
|
|
count++; |
867 |
|
|
return count; |
868 |
|
|
|
869 |
|
|
case GPGME_ATTR_KEYID: |
870 |
|
|
for( dat.k = &key->keys; dat.k; dat.k = dat.k->next ) |
871 |
|
|
count++; |
872 |
|
|
return count; |
873 |
|
|
|
874 |
|
|
case GPGME_ATTR_REVKEY_FPR: |
875 |
|
|
for( dat.r = key->rvks; dat.r; dat.r = dat.r->next ) |
876 |
|
|
count++; |
877 |
|
|
return count; |
878 |
|
|
|
879 |
|
|
case GPGME_ATTR_SIG_KEYID: |
880 |
twoaday |
17 |
for (dat.s = key->sigs; dat.s; dat.s = dat.s->next) |
881 |
twoaday |
2 |
count++; |
882 |
|
|
return count; |
883 |
|
|
} |
884 |
|
|
return 0; |
885 |
|
|
} /* gpgme_key_count_items */ |
886 |
|
|
|
887 |
|
|
|
888 |
|
|
gpgme_key_t |
889 |
|
|
_gpgme_key_new_fromkeyid (const char * keyid) |
890 |
|
|
{ |
891 |
|
|
gpgme_key_t key; |
892 |
|
|
|
893 |
|
|
if (!keyid) |
894 |
|
|
return NULL; |
895 |
|
|
if (_gpgme_key_new (&key)) |
896 |
|
|
return NULL; |
897 |
|
|
memset (key->keys.keyid, 0, sizeof key->keys.keyid); |
898 |
|
|
strncpy (key->keys.keyid, keyid, DIM (key->keys.keyid)-1); |
899 |
|
|
return key; |
900 |
|
|
} /* _gpgme_key_new_fromkeyid */ |
901 |
|
|
|
902 |
|
|
|
903 |
|
|
int |
904 |
twoaday |
11 |
gpgme_key_cability_from_algo (gpgme_pk_cipher_t algo) |
905 |
twoaday |
2 |
{ |
906 |
twoaday |
17 |
switch (algo) { |
907 |
twoaday |
2 |
case GPGME_PK_DSA: |
908 |
|
|
case GPGME_PK_RSA_S: |
909 |
|
|
return GPGME_KEY_CANSIGN; |
910 |
|
|
|
911 |
|
|
case GPGME_PK_RSA: |
912 |
|
|
case GPGME_PK_ELG_ES: |
913 |
|
|
return GPGME_KEY_CANSIGN|GPGME_KEY_CANENCR; |
914 |
|
|
|
915 |
|
|
case GPGME_PK_RSA_E: |
916 |
|
|
case GPGME_PK_ELG_E: |
917 |
|
|
return GPGME_KEY_CANENCR; |
918 |
twoaday |
7 |
} |
919 |
twoaday |
2 |
|
920 |
|
|
return 0; |
921 |
|
|
} /* gpgme_key_cability_from_algo */ |
922 |
twoaday |
11 |
|
923 |
|
|
|
924 |
twoaday |
17 |
gpgme_error_t |
925 |
twoaday |
11 |
gpgme_key_append (gpgme_key_t dst, gpgme_key_t src, int idx) |
926 |
|
|
{ |
927 |
|
|
struct subkey_s *s, *key; |
928 |
|
|
|
929 |
|
|
for (s = &src->keys; idx; idx--, s = s->next) |
930 |
|
|
; |
931 |
|
|
|
932 |
|
|
key = _gpgme_key_add_subkey (dst); |
933 |
|
|
key->expires = s->expires; |
934 |
|
|
key->flags = s->flags; |
935 |
|
|
key->key_algo = s->key_algo; |
936 |
|
|
key->key_len = s->key_len; |
937 |
|
|
key->timestamp = s->timestamp; |
938 |
|
|
key->fingerprint = strdup (s->fingerprint); |
939 |
|
|
strcpy (key->keyid, s->keyid); |
940 |
|
|
|
941 |
|
|
return 0; |
942 |
|
|
} |