import works
[gnupg.git] / g10 / getkey.c
1 /* getkey.c -  Get a key from the database
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * G10 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <ctype.h>
27 #include "util.h"
28 #include "packet.h"
29 #include "memory.h"
30 #include "iobuf.h"
31 #include "keydb.h"
32 #include "options.h"
33
34 #define MAX_PKC_CACHE_ENTRIES 500
35
36
37 typedef struct keyid_list {
38     struct keyid_list *next;
39     u32 keyid[2];
40 } *keyid_list_t;
41
42 typedef struct user_id_db {
43     struct user_id_db *next;
44     u32 keyid[2];
45     int len;
46     char name[1];
47 } *user_id_db_t;
48
49 typedef struct pkc_cache_entry {
50     struct pkc_cache_entry *next;
51     u32 keyid[2];
52     PKT_public_cert *pkc;
53 } *pkc_cache_entry_t;
54
55 typedef struct enum_seckey_context {
56     int eof;
57     STRLIST sl;
58     IOBUF iobuf;
59 } enum_seckey_context_t;
60
61
62 static STRLIST keyrings;
63 static STRLIST secret_keyrings;
64
65 static keyid_list_t unknown_keyids;
66 static user_id_db_t user_id_db;
67 static pkc_cache_entry_t pkc_cache;
68 static int pkc_cache_entries;   /* number of entries in pkc cache */
69
70
71 static int scan_keyring( PKT_public_cert *pkc, u32 *keyid,
72                          const char *name, const char *filename );
73 static int scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
74                                 const char *name, const char *filename);
75
76 /* note this function may be called before secure memory is
77  * available */
78 void
79 add_keyring( const char *name )
80 {
81     STRLIST sl;
82     int rc;
83
84     /* FIXME: check wether this one is available etc */
85     /* maybe we should do this later */
86     if( *name != '/' ) { /* do tilde expansion etc */
87         char *p ;
88
89         if( strchr(name, '/') )
90             p = make_filename(name, NULL);
91         else
92             p = make_filename(opt.homedir, name, NULL);
93         sl = m_alloc( sizeof *sl + strlen(p) );
94         strcpy(sl->d, p );
95         m_free(p);
96     }
97     else {
98         sl = m_alloc( sizeof *sl + strlen(name) );
99         strcpy(sl->d, name );
100     }
101     sl->next = keyrings;
102     keyrings = sl;
103
104     /* FIXME: We should remove much out of this module and
105      * combine it with the keyblock stuff from ringedit.c
106      * For now we will simple add the filename as keyblock resource
107      */
108     rc = add_keyblock_resource( sl->d, 0, 0 );
109     if( rc )
110         log_error("keyblock resource '%s': %s\n", sl->d, g10_errstr(rc) );
111 }
112
113
114 /****************
115  * Get the name of the keyrings, start with a sequence number of 0.
116  */
117 const char *
118 get_keyring( int sequence )
119 {
120     STRLIST sl;
121
122     for(sl = keyrings; sl && sequence; sl = sl->next, sequence-- )
123         ;
124     return sl? sl->d : NULL;
125 }
126
127
128 void
129 add_secret_keyring( const char *name )
130 {
131     STRLIST sl;
132     int rc;
133
134     /* FIXME: check wether this one is available etc */
135     /* my be we should do this later */
136     if( *name != '/' ) { /* do tilde expansion etc */
137         char *p ;
138
139         if( strchr(name, '/') )
140             p = make_filename(name, NULL);
141         else
142             p = make_filename(opt.homedir, name, NULL);
143         sl = m_alloc( sizeof *sl + strlen(p) );
144         strcpy(sl->d, p );
145         m_free(p);
146     }
147     else {
148         sl = m_alloc( sizeof *sl + strlen(name) );
149         strcpy(sl->d, name );
150     }
151     sl->next = secret_keyrings;
152     secret_keyrings = sl;
153
154     /* FIXME: We should remove much out of this mpdule and
155      * combine it with the keyblock stuff from ringedit.c
156      * For now we will simple add the filename as keyblock resource
157      */
158     rc = add_keyblock_resource( sl->d, 0, 1 );
159     if( rc )
160         log_error("secret keyblock resource '%s': %s\n", sl->d, g10_errstr(rc));
161 }
162
163
164 void
165 cache_public_cert( PKT_public_cert *pkc )
166 {
167     pkc_cache_entry_t ce;
168     u32 keyid[2];
169
170     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
171         || pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
172         keyid_from_pkc( pkc, keyid );
173     }
174     else
175         return; /* don't know how to get the keyid */
176
177     for( ce = pkc_cache; ce; ce = ce->next )
178         if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
179             if( DBG_CACHE )
180                 log_debug("cache_public_cert: already in cache\n");
181             return;
182         }
183
184     if( pkc_cache_entries > MAX_PKC_CACHE_ENTRIES ) {
185         /* FIMXE: use another algorithm to free some cache slots */
186         if( pkc_cache_entries == MAX_PKC_CACHE_ENTRIES )  {
187             pkc_cache_entries++;
188             log_info("too many entries in pkc cache - disabled\n");
189         }
190         ce = pkc_cache;
191         free_public_cert( ce->pkc );
192     }
193     else {
194         pkc_cache_entries++;
195         ce = m_alloc( sizeof *ce );
196         ce->next = pkc_cache;
197         pkc_cache = ce;
198     }
199     ce->pkc = copy_public_cert( NULL, pkc );
200     ce->keyid[0] = keyid[0];
201     ce->keyid[1] = keyid[1];
202 }
203
204
205 /****************
206  * Store the association of keyid and userid
207  */
208 void
209 cache_user_id( PKT_user_id *uid, u32 *keyid )
210 {
211     user_id_db_t r;
212
213     for(r=user_id_db; r; r = r->next )
214         if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
215             if( DBG_CACHE )
216                 log_debug("cache_user_id: already in cache\n");
217             return;
218         }
219
220     r = m_alloc( sizeof *r + uid->len-1 );
221     r->keyid[0] = keyid[0];
222     r->keyid[1] = keyid[1];
223     r->len = uid->len;
224     memcpy(r->name, uid->name, r->len);
225     r->next = user_id_db;
226     user_id_db = r;
227 }
228
229
230
231 /****************
232  * Get a public key and store it into the allocated pkc
233  * can be called with PKC set to NULL to just read it into some
234  * internal structures.
235  */
236 int
237 get_pubkey( PKT_public_cert *pkc, u32 *keyid )
238 {
239     keyid_list_t kl;
240     int internal = 0;
241     int rc = 0;
242     pkc_cache_entry_t ce;
243     STRLIST sl;
244
245
246     /* lets see wether we checked the keyid already */
247     for( kl = unknown_keyids; kl; kl = kl->next )
248         if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
249             return G10ERR_NO_PUBKEY; /* already checked and not found */
250
251     /* 1. Try to get it from our cache */
252     for( ce = pkc_cache; ce; ce = ce->next )
253         if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
254             if( pkc )
255                 copy_public_cert( pkc, ce->pkc );
256             return 0;
257         }
258
259     /* more init stuff */
260     if( !pkc ) {
261         pkc = m_alloc_clear( sizeof *pkc );
262         internal++;
263     }
264
265
266     /* 2. Try to get it from the keyrings */
267     for(sl = keyrings; sl; sl = sl->next )
268         if( !scan_keyring( pkc, keyid, NULL, sl->d ) )
269             goto leave;
270
271     /* 3. Try to get it from a key server */
272
273     /* 4. not found: store it for future reference */
274     kl = m_alloc( sizeof *kl );
275     kl->keyid[0] = keyid[0];
276     kl->keyid[1] = keyid[1];
277     kl->next = unknown_keyids;
278     unknown_keyids = kl;
279     rc = G10ERR_NO_PUBKEY;
280
281   leave:
282     if( !rc )
283         cache_public_cert( pkc );
284     if( internal )
285         m_free(pkc);
286     return rc;
287 }
288
289
290 /****************
291  * Try to get the pubkey by the userid. This functions looks for the
292  * first pubkey certificate which has the given name in a user_id.
293  * if pkc has the pubkey algo set, the function will only return
294  * a pubkey with that algo.
295  *
296  * - If the username starts with 8,9,16 or 17 hex-digits (the first one
297  *   must be in the range 0..9), this is considered a keyid; depending
298  *   on the length a short or complete one.
299  * - If the username starts with 32,33,40 or 41 hex-digits (the first one
300  *   must be in the range 0..9), this is considered a fingerprint.
301  *   (Not yet implemented)
302  * - If the username starts with a left angle, we assume it is a complete
303  *   email address and look only at this part.
304  * - If the userid start with an '=' an exact compare is done; this may
305  *   also follow the keyid in which case both parts are matched.
306  *   (Not yet implemented)
307  *
308  */
309 int
310 get_pubkey_byname( PKT_public_cert *pkc, const char *name )
311 {
312     int internal = 0;
313     int rc = 0;
314     STRLIST sl;
315     const char *s;
316     u32 keyid[2] = {0}; /* init to avoid compiler warning */
317     int use_keyid=0;
318
319     /* check what kind of name it is */
320     for(s = name; *s && isspace(*s); s++ )
321         ;
322     if( isdigit( *s ) ) { /* a keyid */
323         int i;
324         char buf[9];
325
326         for(i=0; isxdigit(s[i]); i++ )
327             ;
328         if( s[i] && !isspace(s[i]) ) /* not terminated by EOS or blank*/
329             rc = G10ERR_INV_USER_ID;
330         else if( i == 8 || (i == 9 && *s == '0') ) { /* short keyid */
331             if( i==9 )
332                 s++;
333             keyid[1] = strtoul( s, NULL, 16 );
334             use_keyid++;
335         }
336         else if( i == 16 || (i == 17 && *s == '0') ) { /* complete keyid */
337             if( i==17 )
338                 s++;
339             mem2str(buf, s, 9 );
340             keyid[0] = strtoul( buf, NULL, 16 );
341             keyid[1] = strtoul( s+8, NULL, 16 );
342             return get_pubkey( pkc, keyid );
343         }
344         else
345             rc = G10ERR_INV_USER_ID;
346     }
347     else if( *s == '<' ) { /* an email address */
348         /* for now handled like a substring */
349         /* a keyserver might use this for quicker access */
350     }
351     else if( *s == '=' ) { /* exact search */
352         rc = G10ERR_INV_USER_ID; /* nox yet implemented */
353     }
354     else if( *s == '#' ) { /* use local id */
355         rc = G10ERR_INV_USER_ID; /* nox yet implemented */
356     }
357     else if( *s == '*' ) { /* substring search */
358         name++;
359     }
360     else if( !*s )  /* empty string */
361         rc = G10ERR_INV_USER_ID;
362
363     if( rc )
364         goto leave;
365
366
367
368     if( !pkc ) {
369         pkc = m_alloc_clear( sizeof *pkc );
370         internal++;
371     }
372
373     /* 2. Try to get it from the keyrings */
374     for(sl = keyrings; sl; sl = sl->next )
375         if( use_keyid ) {
376             if( !scan_keyring( pkc, keyid, name, sl->d ) )
377                 goto leave;
378         }
379         else {
380             if( !scan_keyring( pkc, NULL, name, sl->d ) )
381                 goto leave;
382         }
383     /* 3. Try to get it from a key server */
384
385     /* 4. not found: store it for future reference */
386     rc = G10ERR_NO_PUBKEY;
387
388   leave:
389     if( internal )
390         m_free(pkc);
391     return rc;
392 }
393
394
395 /****************
396  * Get a secret key and store it into skey
397  */
398 int
399 get_seckey( PKT_secret_cert *skc, u32 *keyid )
400 {
401     STRLIST sl;
402     int rc=0;
403
404     for(sl = secret_keyrings; sl; sl = sl->next )
405         if( !(rc=scan_secret_keyring( skc, keyid, NULL, sl->d )) )
406             goto found;
407     /* fixme: look at other places */
408     goto leave;
409
410   found:
411     /* get the secret key (this may prompt for a passprase to
412      * unlock the secret key
413      */
414     if( (rc = check_secret_key( skc )) )
415         goto leave;
416
417   leave:
418     return rc;
419 }
420
421 /****************
422  * Get a secret key by name and store it into skc
423  * If NAME is NULL use the default certificate
424  */
425 int
426 get_seckey_byname( PKT_secret_cert *skc, const char *name, int unprotect )
427 {
428     STRLIST sl;
429     int rc=0;
430
431     for(sl = secret_keyrings; sl; sl = sl->next )
432         if( !(rc=scan_secret_keyring( skc, NULL, name, sl->d ) ) )
433             goto found;
434     /* fixme: look at other places */
435     goto leave;
436
437   found:
438     /* get the secret key (this may prompt for a passprase to
439      * unlock the secret key
440      */
441     if( unprotect )
442         if( (rc = check_secret_key( skc )) )
443             goto leave;
444
445   leave:
446     return rc;
447 }
448
449
450
451
452
453 /****************
454  * scan the keyring and look for either the keyid or the name.
455  * If both, keyid and name are given, look for keyid but use only
456  * the low word of it (name is only used as a flag to indicate this mode
457  * of operation).
458  */
459 static int
460 scan_keyring( PKT_public_cert *pkc, u32 *keyid,
461               const char *name, const char *filename )
462 {
463     compress_filter_context_t cfx;
464     int rc=0;
465     int found = 0;
466     IOBUF a;
467     PACKET pkt;
468     int save_mode;
469     u32 akeyid[2];
470     PKT_public_cert *last_pk = NULL;
471     int shortkeyid;
472
473     shortkeyid = keyid && name;
474     if( shortkeyid )
475         name = NULL; /* not used anymore */
476
477     if( !(a = iobuf_open( filename ) ) ) {
478         log_debug("scan_keyring: can't open '%s'\n", filename );
479         return G10ERR_KEYRING_OPEN;
480     }
481
482     if( !DBG_CACHE )
483         ;
484     else if( shortkeyid )
485         log_debug("scan_keyring %s for %08lx\n",  filename, (ulong)keyid[1] );
486     else if( name )
487         log_debug("scan_keyring %s for '%s'\n",  filename, name );
488     else if( keyid )
489         log_debug("scan_keyring %s for %08lx %08lx\n",  filename,
490                                              (ulong)keyid[0], (ulong)keyid[1] );
491     else
492         log_debug("scan_keyring %s (all)\n",  filename );
493
494     save_mode = set_packet_list_mode(0);
495     init_packet(&pkt);
496     while( (rc=parse_packet(a, &pkt)) != -1 ) {
497         if( rc )
498             ; /* e.g. unknown packet */
499         else if( keyid && found && pkt.pkttype == PKT_PUBLIC_CERT ) {
500             log_error("Hmmm, pubkey without an user id in '%s'\n", filename);
501             goto leave;
502         }
503         else if( pkt.pkttype == PKT_COMPRESSED ) {
504             memset( &cfx, 0, sizeof cfx );
505             if( pkt.pkt.compressed->algorithm == 1 )
506                 cfx.pgpmode = 1;
507             else if( pkt.pkt.compressed->algorithm != 2  ){
508                 rc = G10ERR_COMPR_ALGO;
509                 log_error("compressed keyring: %s\n", g10_errstr(rc) );
510                 break;
511             }
512
513             pkt.pkt.compressed->buf = NULL;
514             iobuf_push_filter( a, compress_filter, &cfx );
515         }
516         else if( keyid && pkt.pkttype == PKT_PUBLIC_CERT ) {
517             switch( pkt.pkt.public_cert->pubkey_algo ) {
518               case PUBKEY_ALGO_ELGAMAL:
519               case PUBKEY_ALGO_RSA:
520                 keyid_from_pkc( pkt.pkt.public_cert, akeyid );
521                 if( (shortkeyid || akeyid[0] == keyid[0])
522                     && akeyid[1] == keyid[1] ) {
523                     copy_public_cert( pkc, pkt.pkt.public_cert );
524                     found++;
525                 }
526                 break;
527               default:
528                 log_error("cannot handle pubkey algo %d\n",
529                                      pkt.pkt.public_cert->pubkey_algo);
530             }
531         }
532         else if( keyid && found && pkt.pkttype == PKT_USER_ID ) {
533             cache_user_id( pkt.pkt.user_id, keyid );
534             goto leave;
535         }
536         else if( name && pkt.pkttype == PKT_PUBLIC_CERT ) {
537             if( last_pk )
538                 free_public_cert(last_pk);
539             last_pk = pkt.pkt.public_cert;
540             pkt.pkt.public_cert = NULL;
541         }
542         else if( name && pkt.pkttype == PKT_USER_ID ) {
543             if( memistr( pkt.pkt.user_id->name, pkt.pkt.user_id->len, name )) {
544                 if( !last_pk )
545                     log_error("Ooops: no pubkey for userid '%.*s'\n",
546                                 pkt.pkt.user_id->len, pkt.pkt.user_id->name);
547                 else if( pkc->pubkey_algo &&
548                          pkc->pubkey_algo != last_pk->pubkey_algo )
549                     log_info("skipping id '%.*s': want algo %d, found %d\n",
550                                 pkt.pkt.user_id->len, pkt.pkt.user_id->name,
551                                 pkc->pubkey_algo, last_pk->pubkey_algo );
552                 else {
553                     copy_public_cert( pkc, last_pk );
554                     goto leave;
555                 }
556             }
557         }
558         else if( !keyid && !name && pkt.pkttype == PKT_PUBLIC_CERT ) {
559             if( last_pk )
560                 free_public_cert(last_pk);
561             last_pk = pkt.pkt.public_cert;
562             pkt.pkt.public_cert = NULL;
563         }
564         else if( !keyid && !name && pkt.pkttype == PKT_USER_ID ) {
565             if( !last_pk )
566                 log_error("Ooops: no pubkey for userid '%.*s'\n",
567                             pkt.pkt.user_id->len, pkt.pkt.user_id->name);
568             else {
569                 if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
570                     || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
571                      keyid_from_pkc( last_pk, akeyid );
572                      cache_user_id( pkt.pkt.user_id, akeyid );
573                 }
574                 cache_public_cert( last_pk );
575             }
576         }
577         free_packet(&pkt);
578     }
579     rc = G10ERR_NO_PUBKEY;
580
581   leave:
582     if( last_pk )
583         free_public_cert(last_pk);
584     free_packet(&pkt);
585     iobuf_close(a);
586     set_packet_list_mode(save_mode);
587     return rc;
588 }
589
590
591 /****************
592  * This is the function to get a secret key. We use an extra function,
593  * so that we can easily add special handling for secret keyrings
594  * PKT returns the secret key certificate.
595  */
596 static int
597 scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
598                      const char *name, const char *filename )
599 {
600     int rc=0;
601     int found = 0;
602     IOBUF a;
603     PACKET pkt;
604     int save_mode;
605     u32 akeyid[2];
606     PKT_secret_cert *last_pk = NULL;
607     int get_first;
608     u32 dummy_keyid[2];
609
610     get_first = !keyid && !name;
611     if( get_first )
612         keyid = dummy_keyid;
613
614     if( !(a = iobuf_open( filename ) ) ) {
615         log_debug("scan_secret_keyring: can't open '%s'\n", filename );
616         return G10ERR_KEYRING_OPEN;
617     }
618
619     save_mode = set_packet_list_mode(0);
620     init_packet(&pkt);
621     while( (rc=parse_packet(a, &pkt)) != -1 ) {
622         if( rc )
623             ; /* e.g. unknown packet */
624         else if( keyid && found && pkt.pkttype == PKT_SECRET_CERT ) {
625             log_error("Hmmm, seckey without an user id in '%s'\n", filename);
626             goto leave;
627         }
628         else if( keyid && pkt.pkttype == PKT_SECRET_CERT ) {
629             switch( pkt.pkt.secret_cert->pubkey_algo ) {
630               case PUBKEY_ALGO_ELGAMAL:
631               case PUBKEY_ALGO_RSA:
632                 if( get_first ) {
633                     copy_secret_cert( skc, pkt.pkt.secret_cert );
634                     found++;
635                 }
636                 else {
637                     keyid_from_skc( pkt.pkt.secret_cert, akeyid );
638                     if( (akeyid[0] == keyid[0] && akeyid[1] == keyid[1]) ) {
639                         copy_secret_cert( skc, pkt.pkt.secret_cert );
640                         found++;
641                     }
642                 }
643                 break;
644               default:
645                 log_error("cannot handle pubkey algo %d\n",
646                                      pkt.pkt.secret_cert->pubkey_algo);
647             }
648         }
649         else if( keyid && found && pkt.pkttype == PKT_USER_ID ) {
650             goto leave;
651         }
652         else if( name && pkt.pkttype == PKT_SECRET_CERT ) {
653             if( last_pk )
654                 free_secret_cert(last_pk);
655             last_pk = pkt.pkt.secret_cert;
656             pkt.pkt.secret_cert = NULL;
657         }
658         else if( name && pkt.pkttype == PKT_USER_ID ) {
659             if( memistr( pkt.pkt.user_id->name, pkt.pkt.user_id->len, name )) {
660                 if( !last_pk )
661                     log_error("Ooops: no seckey for userid '%.*s'\n",
662                                 pkt.pkt.user_id->len, pkt.pkt.user_id->name);
663                 else if( skc->pubkey_algo &&
664                          skc->pubkey_algo != last_pk->pubkey_algo )
665                     log_info("skipping id '%.*s': want algo %d, found %d\n",
666                                 pkt.pkt.user_id->len, pkt.pkt.user_id->name,
667                                 skc->pubkey_algo, last_pk->pubkey_algo );
668                 else {
669                     copy_secret_cert( skc, last_pk );
670                     goto leave;
671                 }
672             }
673         }
674         else if( !keyid && !name && pkt.pkttype == PKT_SECRET_CERT ) {
675             if( last_pk )
676                 free_secret_cert(last_pk);
677             last_pk = pkt.pkt.secret_cert;
678             pkt.pkt.secret_cert = NULL;
679         }
680         else if( !keyid && !name && pkt.pkttype == PKT_USER_ID ) {
681             if( !last_pk )
682                 log_error("Ooops: no seckey for userid '%.*s'\n",
683                             pkt.pkt.user_id->len, pkt.pkt.user_id->name);
684             else {
685                 if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
686                    || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
687                     keyid_from_skc( last_pk, akeyid );
688                     cache_user_id( pkt.pkt.user_id, akeyid );
689                 }
690             }
691         }
692         free_packet(&pkt);
693     }
694     rc = G10ERR_NO_SECKEY;
695
696   leave:
697     if( last_pk )
698         free_secret_cert(last_pk);
699     free_packet(&pkt);
700     iobuf_close(a);
701     set_packet_list_mode(save_mode);
702     return rc;
703 }
704
705
706 /****************
707  * Enumerate all secret keys.  Caller must use these procedure:
708  *  1) create a void pointer and initialize it to NULL
709  *  2) pass this void pointer by reference to this function
710  *     and provide space for the secret key (pass a buffer for skc)
711  *  3) call this function as long as it does not return -1
712  *     to indicate EOF.
713  *  4) Always call this function a last time with SKC set to NULL,
714  *     so that can free it's context.
715  *
716  * Return
717  */
718 int
719 enum_secret_keys( void **context, PKT_secret_cert *skc )
720 {
721     int rc=0;
722     PACKET pkt;
723     int save_mode;
724     enum_seckey_context_t *c = *context;
725
726     if( !c ) { /* make a new context */
727         c = m_alloc_clear( sizeof *c );
728         *context = c;
729         c->sl = secret_keyrings;
730     }
731
732     if( !skc ) { /* free the context */
733         m_free( c );
734         *context = NULL;
735         return 0;
736     }
737
738     if( c->eof )
739         return -1;
740
741     for( ; c->sl; c->sl = c->sl->next ) {
742         if( !c->iobuf ) {
743             if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) {
744                 log_error("enum_secret_keys: can't open '%s'\n", c->sl->d );
745                 continue; /* try next file */
746             }
747         }
748
749         save_mode = set_packet_list_mode(0);
750         init_packet(&pkt);
751         while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
752             if( rc )
753                 ; /* e.g. unknown packet */
754             else if( pkt.pkttype == PKT_SECRET_CERT ) {
755                 copy_secret_cert( skc, pkt.pkt.secret_cert );
756                 set_packet_list_mode(save_mode);
757                 return 0; /* found */
758             }
759             free_packet(&pkt);
760         }
761         set_packet_list_mode(save_mode);
762         iobuf_close(c->iobuf); c->iobuf = NULL;
763     }
764     c->eof = 1;
765     return -1;
766 }
767
768
769 /****************
770  * Return a string with a printable representation of the user_id.
771  * this string must be freed by m_free.
772  */
773 char*
774 get_user_id_string( u32 *keyid )
775 {
776     user_id_db_t r;
777     char *p;
778     int pass=0;
779     /* try it two times; second pass reads from keyrings */
780     do {
781         for(r=user_id_db; r; r = r->next )
782             if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
783                 p = m_alloc( r->len + 10 );
784                 sprintf(p, "%08lX %.*s", (ulong)keyid[1], r->len, r->name );
785                 return p;
786             }
787     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
788     p = m_alloc( 15 );
789     sprintf(p, "%08lX [?]", (ulong)keyid[1] );
790     return p;
791 }
792
793 char*
794 get_user_id( u32 *keyid, size_t *rn )
795 {
796     user_id_db_t r;
797     char *p;
798     int pass=0;
799     /* try it two times; second pass reads from keyrings */
800     do {
801         for(r=user_id_db; r; r = r->next )
802             if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
803                 p = m_alloc( r->len );
804                 memcpy(p, r->name, r->len );
805                 *rn = r->len;
806                 return p;
807             }
808     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
809     p = m_alloc( 19 );
810     memcpy(p, "[User id not found]", 19 );
811     *rn = 19;
812     return p;
813 }
814
815