cd94fa5523502efbe626e4de4d6ae56f24fd0f0e
[gnupg.git] / sm / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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  * GnuPG 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 <errno.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include "gpgsm.h"
32 #include "../kbx/keybox.h"
33 #include "keydb.h" 
34 #include "i18n.h"
35
36 #define DIRSEP_C '/'
37
38 #define spacep(a) ((a) == ' ' || (a) == '\t')
39
40 static int active_handles;
41
42 typedef enum {
43     KEYDB_RESOURCE_TYPE_NONE = 0,
44     KEYDB_RESOURCE_TYPE_KEYBOX
45 } KeydbResourceType;
46 #define MAX_KEYDB_RESOURCES 20
47
48 struct resource_item {
49   KeydbResourceType type;
50   union {
51     KEYBOX_HANDLE kr;
52   } u;
53   void *token;
54   int secret;
55 };
56
57 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
58 static int used_resources;
59
60 struct keydb_handle {
61   int locked;
62   int found;
63   int current;
64   int used; /* items in active */
65   struct resource_item active[MAX_KEYDB_RESOURCES];
66 };
67
68
69 static int lock_all (KEYDB_HANDLE hd);
70 static void unlock_all (KEYDB_HANDLE hd);
71
72
73 /*
74  * Register a resource (which currently may only be a keybox file).
75  * The first keybox which is added by this function is
76  * created if it does not exist.
77  * Note: this function may be called before secure memory is
78  * available.
79  */
80 int
81 keydb_add_resource (const char *url, int force, int secret)
82 {
83   static int any_secret, any_public;
84   const char *resname = url;
85   char *filename = NULL;
86   int rc = 0; 
87   FILE *fp;
88   KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
89   const char *created_fname = NULL;
90
91   /* Do we have an URL?
92      gnupg-kbx:filename := this is a plain keybox
93      filename := See what is is, but create as plain keybox.
94   */
95   if (strlen (resname) > 10) 
96     {
97       if (!strncmp (resname, "gnupg-kbx:", 10) )
98         {
99           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
100           resname += 10;
101         }
102 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
103       else if (strchr (resname, ':'))
104         {
105           log_error ("invalid key resource URL `%s'\n", url );
106           rc = GNUPG_General_Error;
107           goto leave;
108         }
109 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
110     }
111
112   if (*resname != DIRSEP_C )
113     { /* do tilde expansion etc */
114       if (strchr(resname, DIRSEP_C) )
115         filename = make_filename (resname, NULL);
116       else
117         filename = make_filename (opt.homedir, resname, NULL);
118     }
119   else
120     filename = xstrdup (resname);
121   
122   if (!force)
123     force = secret? !any_secret : !any_public;
124   
125   /* see whether we can determine the filetype */
126   if (rt == KEYDB_RESOURCE_TYPE_NONE)
127     {
128       FILE *fp2 = fopen( filename, "rb" );
129       
130       if (fp2) {
131         u32 magic;
132         
133         /* FIXME: check for the keybox magic */
134         if (fread( &magic, 4, 1, fp2) == 1 ) 
135           {
136             if (magic == 0x13579ace || magic == 0xce9a5713)
137               ; /* GDBM magic - no more support */
138             else
139               rt = KEYDB_RESOURCE_TYPE_KEYBOX;
140           }
141         else /* maybe empty: assume ring */
142           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
143         fclose (fp2);
144       }
145       else /* no file yet: create ring */
146         rt = KEYDB_RESOURCE_TYPE_KEYBOX;
147     }
148     
149   switch (rt)
150     {
151     case KEYDB_RESOURCE_TYPE_NONE:
152       log_error ("unknown type of key resource `%s'\n", url );
153       rc = GNUPG_General_Error;
154       goto leave;
155       
156     case KEYDB_RESOURCE_TYPE_KEYBOX:
157       fp = fopen (filename, "rb");
158       if (!fp && !force)
159         {
160           rc = GNUPG_File_Open_Error;
161           goto leave;
162         }
163       
164       if (!fp)
165         { /* no file */
166 #if 0 /* no autocreate of the homedirectory yet */
167           {
168             char *last_slash_in_filename;
169             
170             last_slash_in_filename = strrchr (filename, DIRSEP_C);
171             *last_slash_in_filename = 0;
172             if (access (filename, F_OK))
173               { /* on the first time we try to create the default
174                    homedir and in this case the process will be
175                    terminated, so that on the next invocation can
176                    read the options file in on startup */
177                 try_make_homedir (filename);
178                 rc = GNUPG_File_Open_Error;
179                 *last_slash_in_filename = DIRSEP_C;
180                 goto leave;
181               }
182             *last_slash_in_filename = DIRSEP_C;
183           }
184 #endif
185           fp = fopen (filename, "w");
186           if (!fp)
187             {
188               log_error (_("error creating keybox `%s': %s\n"),
189                          filename, strerror(errno));
190               rc = GNUPG_File_Create_Error;
191               goto leave;
192             }
193
194           if (!opt.quiet)
195             log_info (_("keybox `%s' created\n"), filename);
196           created_fname = filename;
197         }
198         fclose (fp);
199         fp = NULL;
200         /* now regsiter the file */
201         {
202           void *token = keybox_register_file (filename, secret);
203           if (!token)
204             ; /* already registered - ignore it */
205           else if (used_resources >= MAX_KEYDB_RESOURCES)
206             rc = GNUPG_Resource_Limit;
207           else 
208             {
209               all_resources[used_resources].type = rt;
210               all_resources[used_resources].u.kr = NULL; /* Not used here */
211               all_resources[used_resources].token = token;
212               all_resources[used_resources].secret = secret;
213               used_resources++;
214             }
215         }
216         break;
217     default:
218       log_error ("resource type of `%s' not supported\n", url);
219       rc = GNUPG_Not_Supported;
220       goto leave;
221     }
222
223   /* fixme: check directory permissions and print a warning */
224
225  leave:
226   if (rc)
227     log_error ("keyblock resource `%s': %s\n", filename, gnupg_strerror(rc));
228   else if (secret)
229     any_secret = 1;
230   else
231     any_public = 1;
232   xfree (filename);
233   return rc;
234 }
235
236
237 KEYDB_HANDLE
238 keydb_new (int secret)
239 {
240   KEYDB_HANDLE hd;
241   int i, j;
242   
243   hd = xcalloc (1, sizeof *hd);
244   hd->found = -1;
245   
246   assert (used_resources <= MAX_KEYDB_RESOURCES);
247   for (i=j=0; i < used_resources; i++)
248     {
249       if (!all_resources[i].secret != !secret)
250         continue;
251       switch (all_resources[i].type)
252         {
253         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
254           break;
255         case KEYDB_RESOURCE_TYPE_KEYBOX:
256           hd->active[j].type   = all_resources[i].type;
257           hd->active[j].token  = all_resources[i].token;
258           hd->active[j].secret = all_resources[i].secret;
259           hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
260           if (!hd->active[j].u.kr) {
261             xfree (hd);
262             return NULL; /* fixme: release all previously allocated handles*/
263           }
264           j++;
265           break;
266         }
267     }
268   hd->used = j;
269   
270   active_handles++;
271   return hd;
272 }
273
274 void 
275 keydb_release (KEYDB_HANDLE hd)
276 {
277   int i;
278   
279   if (!hd)
280     return;
281   assert (active_handles > 0);
282   active_handles--;
283
284   unlock_all (hd);
285   for (i=0; i < hd->used; i++)
286     {
287       switch (hd->active[i].type) 
288         {
289         case KEYDB_RESOURCE_TYPE_NONE:
290           break;
291         case KEYDB_RESOURCE_TYPE_KEYBOX:
292           keybox_release (hd->active[i].u.kr);
293           break;
294         }
295     }
296
297     xfree (hd);
298 }
299
300
301 /* Return the name of the current resource.  This is function first
302    looks for the last found found, then for the current search
303    position, and last returns the first available resource.  The
304    returned string is only valid as long as the handle exists.  This
305    function does only return NULL if no handle is specified, in all
306    other error cases an empty string is returned.  */
307 const char *
308 keydb_get_resource_name (KEYDB_HANDLE hd)
309 {
310   int idx;
311   const char *s = NULL;
312   
313   if (!hd) 
314     return NULL;
315
316   if ( hd->found >= 0 && hd->found < hd->used) 
317     idx = hd->found;
318   else if ( hd->current >= 0 && hd->current < hd->used) 
319     idx = hd->current;
320   else
321     idx = 0;
322
323   switch (hd->active[idx].type) 
324     {
325     case KEYDB_RESOURCE_TYPE_NONE:
326       s = NULL; 
327       break;
328     case KEYDB_RESOURCE_TYPE_KEYBOX:
329       s = keybox_get_resource_name (hd->active[idx].u.kr);
330       break;
331     }
332   
333   return s? s: "";
334 }
335
336
337 \f
338 static int 
339 lock_all (KEYDB_HANDLE hd)
340 {
341   int i, rc = 0;
342
343   for (i=0; !rc && i < hd->used; i++) 
344     {
345       switch (hd->active[i].type) 
346         {
347         case KEYDB_RESOURCE_TYPE_NONE:
348           break;
349         case KEYDB_RESOURCE_TYPE_KEYBOX:
350           /* FIXME  rc = keybox_lock (hd->active[i].u.kr, 1);*/
351           break;
352         }
353     }
354
355     if (rc) 
356       {
357         /* revert the already set locks */
358         for (i--; i >= 0; i--) 
359           {
360             switch (hd->active[i].type) 
361               {
362               case KEYDB_RESOURCE_TYPE_NONE:
363                 break;
364               case KEYDB_RESOURCE_TYPE_KEYBOX:
365                 /* Fixme: keybox_lock (hd->active[i].u.kr, 0);*/
366                 break;
367               }
368           }
369       }
370     else
371       hd->locked = 1;
372
373     return rc;
374 }
375
376 static void
377 unlock_all (KEYDB_HANDLE hd)
378 {
379   int i;
380   
381   if (!hd->locked)
382     return;
383
384   for (i=hd->used-1; i >= 0; i--) 
385     {
386       switch (hd->active[i].type) 
387         {
388         case KEYDB_RESOURCE_TYPE_NONE:
389           break;
390         case KEYDB_RESOURCE_TYPE_KEYBOX:
391           /* fixme: keybox_lock (hd->active[i].u.kr, 0);*/
392           break;
393         }
394     }
395   hd->locked = 0;
396 }
397
398 \f
399 #if 0
400 /*
401  * Return the last found keybox.  Caller must free it.
402  * The returned keyblock has the kbode flag bit 0 set for the node with
403  * the public key used to locate the keyblock or flag bit 1 set for 
404  * the user ID node.
405  */
406 int
407 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
408 {
409     int rc = 0;
410
411     if (!hd)
412         return G10ERR_INV_ARG;
413
414     if ( hd->found < 0 || hd->found >= hd->used) 
415         return -1; /* nothing found */
416
417     switch (hd->active[hd->found].type) {
418       case KEYDB_RESOURCE_TYPE_NONE:
419         rc = G10ERR_GENERAL; /* oops */
420         break;
421       case KEYDB_RESOURCE_TYPE_KEYBOX:
422         rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
423         break;
424     }
425
426     return rc;
427 }
428
429 /* 
430  * update the current keyblock with KB
431  */
432 int
433 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
434 {
435     int rc = 0;
436
437     if (!hd)
438         return G10ERR_INV_ARG;
439
440     if ( hd->found < 0 || hd->found >= hd->used) 
441         return -1; /* nothing found */
442
443     if( opt.dry_run )
444         return 0;
445
446     rc = lock_all (hd);
447     if (rc)
448         return rc;
449
450     switch (hd->active[hd->found].type) {
451       case KEYDB_RESOURCE_TYPE_NONE:
452         rc = G10ERR_GENERAL; /* oops */
453         break;
454       case KEYDB_RESOURCE_TYPE_KEYBOX:
455         rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
456         break;
457     }
458
459     unlock_all (hd);
460     return rc;
461 }
462
463
464 /* 
465  * Insert a new KB into one of the resources. 
466  */
467 int
468 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
469 {
470     int rc = -1;
471     int idx;
472
473     if (!hd) 
474         return G10ERR_INV_ARG;
475
476     if( opt.dry_run )
477         return 0;
478
479     if ( hd->found >= 0 && hd->found < hd->used) 
480         idx = hd->found;
481     else if ( hd->current >= 0 && hd->current < hd->used) 
482         idx = hd->current;
483     else
484         return G10ERR_GENERAL;
485
486     rc = lock_all (hd);
487     if (rc)
488         return rc;
489
490     switch (hd->active[idx].type) {
491       case KEYDB_RESOURCE_TYPE_NONE:
492         rc = G10ERR_GENERAL; /* oops */
493         break;
494       case KEYDB_RESOURCE_TYPE_KEYBOX:
495         rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
496         break;
497     }
498
499     unlock_all (hd);
500     return rc;
501 }
502
503 #endif /*disabled code*/
504
505
506 \f
507 /*
508   Return the last found keybox.  Caller must free it.  The returned
509   keyblock has the kbode flag bit 0 set for the node with the public
510   key used to locate the keyblock or flag bit 1 set for the user ID
511   node.  */
512 int
513 keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert)
514 {
515   int rc = 0;
516
517   if (!hd)
518     return GNUPG_Invalid_Value;
519   
520   if ( hd->found < 0 || hd->found >= hd->used) 
521     return -1; /* nothing found */
522   
523   switch (hd->active[hd->found].type) 
524     {
525     case KEYDB_RESOURCE_TYPE_NONE:
526       rc = GNUPG_General_Error; /* oops */
527       break;
528     case KEYDB_RESOURCE_TYPE_KEYBOX:
529       rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
530       break;
531     }
532   
533   return rc;
534 }
535
536 /* 
537  * Insert a new Certificate into one of the resources. 
538  */
539 int
540 keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert)
541 {
542   int rc = -1;
543   int idx;
544   char digest[20];
545   
546   if (!hd) 
547     return GNUPG_Invalid_Value;
548
549   if (opt.dry_run)
550     return 0;
551   
552   if ( hd->found >= 0 && hd->found < hd->used) 
553     idx = hd->found;
554   else if ( hd->current >= 0 && hd->current < hd->used) 
555     idx = hd->current;
556   else
557     return GNUPG_General_Error;
558
559   rc = lock_all (hd);
560   if (rc)
561     return rc;
562
563   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
564
565   switch (hd->active[idx].type) 
566     {
567     case KEYDB_RESOURCE_TYPE_NONE:
568       rc = GNUPG_General_Error;
569       break;
570     case KEYDB_RESOURCE_TYPE_KEYBOX:
571       rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
572       break;
573     }
574   
575   unlock_all (hd);
576   return rc;
577 }
578
579
580
581 /* update the current keyblock with KB */
582 int
583 keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert)
584 {
585   int rc = 0;
586   char digest[20];
587   
588   if (!hd)
589     return GNUPG_Invalid_Value;
590
591   if ( hd->found < 0 || hd->found >= hd->used) 
592     return -1; /* nothing found */
593
594   if (opt.dry_run)
595     return 0;
596
597   rc = lock_all (hd);
598   if (rc)
599     return rc;
600
601   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
602
603   switch (hd->active[hd->found].type) 
604     {
605     case KEYDB_RESOURCE_TYPE_NONE:
606       rc = GNUPG_General_Error; /* oops */
607       break;
608     case KEYDB_RESOURCE_TYPE_KEYBOX:
609       rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
610       break;
611     }
612
613   unlock_all (hd);
614   return rc;
615 }
616
617
618 /* 
619  * The current keyblock or cert will be deleted.
620  */
621 int
622 keydb_delete (KEYDB_HANDLE hd)
623 {
624   int rc = -1;
625   
626   if (!hd)
627     return GNUPG_Invalid_Value;
628
629   if ( hd->found < 0 || hd->found >= hd->used) 
630     return -1; /* nothing found */
631
632   if( opt.dry_run )
633     return 0;
634
635   rc = lock_all (hd);
636   if (rc)
637     return rc;
638
639   switch (hd->active[hd->found].type)
640     {
641     case KEYDB_RESOURCE_TYPE_NONE:
642       rc = GNUPG_General_Error;
643       break;
644     case KEYDB_RESOURCE_TYPE_KEYBOX:
645       rc = keybox_delete (hd->active[hd->found].u.kr);
646       break;
647     }
648
649   unlock_all (hd);
650   return rc;
651 }
652
653
654 \f
655 /*
656  * Locate the default writable key resource, so that the next
657  * operation (which is only relevant for inserts) will be done on this
658  * resource.  
659  */
660 int
661 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
662 {
663   int rc;
664   
665   if (!hd)
666     return GNUPG_Invalid_Value;
667   
668   rc = keydb_search_reset (hd); /* this does reset hd->current */
669   if (rc)
670     return rc;
671   
672   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) 
673     {
674       switch (hd->active[hd->current].type) 
675         {
676         case KEYDB_RESOURCE_TYPE_NONE:
677           BUG();
678           break;
679         case KEYDB_RESOURCE_TYPE_KEYBOX:
680           if (keybox_is_writable (hd->active[hd->current].token))
681             return 0; /* found (hd->current is set to it) */
682           break;
683         }
684     }
685   
686   return -1;
687 }
688
689 /*
690  * Rebuild the caches of all key resources.
691  */
692 void
693 keydb_rebuild_caches (void)
694 {
695   int i;
696   
697   for (i=0; i < used_resources; i++)
698     {
699       if (all_resources[i].secret)
700         continue;
701       switch (all_resources[i].type)
702         {
703         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
704           break;
705         case KEYDB_RESOURCE_TYPE_KEYBOX:
706 /*            rc = keybox_rebuild_cache (all_resources[i].token); */
707 /*            if (rc) */
708 /*              log_error (_("failed to rebuild keybox cache: %s\n"), */
709 /*                         g10_errstr (rc)); */
710           break;
711         }
712     }
713 }
714
715
716
717 /* 
718  * Start the next search on this handle right at the beginning
719  */
720 int 
721 keydb_search_reset (KEYDB_HANDLE hd)
722 {
723   int i, rc = 0;
724   
725   if (!hd)
726     return GNUPG_Invalid_Value;
727
728   hd->current = 0; 
729   hd->found = -1;
730   /* and reset all resources */
731   for (i=0; !rc && i < hd->used; i++) 
732     {
733       switch (hd->active[i].type) 
734         {
735         case KEYDB_RESOURCE_TYPE_NONE:
736           break;
737         case KEYDB_RESOURCE_TYPE_KEYBOX:
738           rc = keybox_search_reset (hd->active[i].u.kr);
739           break;
740         }
741     }
742   return rc; /* fixme: we need to map error codes or share them with
743                 all modules*/
744 }
745
746 /* 
747  * Search through all keydb resources, starting at the current position,
748  * for a keyblock which contains one of the keys described in the DESC array.
749  */
750 int 
751 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
752 {
753   int rc = -1;
754   
755   if (!hd)
756     return GNUPG_Invalid_Value;
757
758   while (rc == -1 && hd->current >= 0 && hd->current < hd->used) 
759     {
760       switch (hd->active[hd->current].type) 
761         {
762         case KEYDB_RESOURCE_TYPE_NONE:
763           BUG(); /* we should never see it here */
764           break;
765         case KEYDB_RESOURCE_TYPE_KEYBOX:
766           rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
767           break;
768         }
769       if (rc == -1) /* EOF -> switch to next resource */
770         hd->current++; 
771       else if (!rc)
772         hd->found = hd->current;
773     }
774   
775   return rc; 
776 }
777
778
779 int
780 keydb_search_first (KEYDB_HANDLE hd)
781 {
782   KEYDB_SEARCH_DESC desc;
783   
784   memset (&desc, 0, sizeof desc);
785   desc.mode = KEYDB_SEARCH_MODE_FIRST;
786   return keydb_search (hd, &desc, 1);
787 }
788
789 int
790 keydb_search_next (KEYDB_HANDLE hd)
791 {
792   KEYDB_SEARCH_DESC desc;
793   
794   memset (&desc, 0, sizeof desc);
795   desc.mode = KEYDB_SEARCH_MODE_NEXT;
796   return keydb_search (hd, &desc, 1);
797 }
798
799 int
800 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
801 {
802   KEYDB_SEARCH_DESC desc;
803   
804   memset (&desc, 0, sizeof desc);
805   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
806 /*    desc.u.kid[0] = kid[0]; */
807 /*    desc.u.kid[1] = kid[1]; */
808   return keydb_search (hd, &desc, 1);
809 }
810
811 int
812 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
813 {
814   KEYDB_SEARCH_DESC desc;
815   
816   memset (&desc, 0, sizeof desc);
817   desc.mode = KEYDB_SEARCH_MODE_FPR;
818   memcpy (desc.u.fpr, fpr, 20);
819   return keydb_search (hd, &desc, 1);
820 }
821
822 int
823 keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
824 {
825   KEYDB_SEARCH_DESC desc;
826   int rc;
827   
828   memset (&desc, 0, sizeof desc);
829   desc.mode = KEYDB_SEARCH_MODE_ISSUER;
830   desc.u.name = issuer;
831   rc = keydb_search (hd, &desc, 1);
832   return rc;
833 }
834
835 int
836 keydb_search_issuer_sn (KEYDB_HANDLE hd,
837                         const char *issuer, const unsigned char *serial)
838 {
839   KEYDB_SEARCH_DESC desc;
840   int rc;
841   
842   memset (&desc, 0, sizeof desc);
843   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
844   desc.sn = serial;
845   desc.u.name = issuer;
846   rc = keydb_search (hd, &desc, 1);
847   return rc;
848 }
849
850 int
851 keydb_search_subject (KEYDB_HANDLE hd, const char *name)
852 {
853   KEYDB_SEARCH_DESC desc;
854   int rc;
855   
856   memset (&desc, 0, sizeof desc);
857   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
858   desc.u.name = name;
859   rc = keydb_search (hd, &desc, 1);
860   return rc;
861 }
862
863
864 static int
865 hextobyte (const unsigned char *s)
866 {
867   int c;
868
869   if( *s >= '0' && *s <= '9' )
870     c = 16 * (*s - '0');
871   else if ( *s >= 'A' && *s <= 'F' )
872     c = 16 * (10 + *s - 'A');
873   else if ( *s >= 'a' && *s <= 'f' )
874     c = 16 * (10 + *s - 'a');
875   else
876     return -1;
877   s++;
878   if ( *s >= '0' && *s <= '9' )
879     c += *s - '0';
880   else if ( *s >= 'A' && *s <= 'F' )
881     c += 10 + *s - 'A';
882   else if ( *s >= 'a' && *s <= 'f' )
883     c += 10 + *s - 'a';
884   else
885     return -1;
886   return c;
887 }
888
889
890 static int
891 classify_user_id (const char *name, 
892                   KEYDB_SEARCH_DESC *desc,
893                   int *force_exact )
894 {
895   const char *s;
896   int hexprefix = 0;
897   int hexlength;
898   int mode = 0;   
899     
900   /* clear the structure so that the mode field is set to zero unless
901    * we set it to the correct value right at the end of this function */
902   memset (desc, 0, sizeof *desc);
903   *force_exact = 0;
904   /* skip leading spaces.  Fixme: what about trailing white space? */
905   for(s = name; *s && spacep(*s); s++ )
906     ;
907
908   switch (*s) 
909     {
910     case 0:  /* empty string is an error */
911       return 0;
912
913     case '.': /* an email address, compare from end */
914       mode = KEYDB_SEARCH_MODE_MAILEND;
915       s++;
916       desc->u.name = s;
917       break;
918
919     case '<': /* an email address */
920       mode = KEYDB_SEARCH_MODE_MAIL;
921       desc->u.name = s;
922       break;
923
924     case '@':  /* part of an email address */
925       mode = KEYDB_SEARCH_MODE_MAILSUB;
926       s++;
927       desc->u.name = s;
928       break;
929
930     case '=':  /* exact compare */
931       mode = KEYDB_SEARCH_MODE_EXACT;
932       s++;
933       desc->u.name = s;
934       break;
935
936     case '*':  /* case insensitive substring search */
937       mode = KEYDB_SEARCH_MODE_SUBSTR;
938       s++;
939       desc->u.name = s;
940       break;
941
942     case '+':  /* compare individual words */
943       mode = KEYDB_SEARCH_MODE_WORDS;
944       s++;
945       desc->u.name = s;
946       break;
947
948     case '/': /* subject's DN */
949       s++;
950       if (!*s || spacep (*s))
951         return 0; /* no DN or prefixed with a space */
952       desc->u.name = s;
953       mode = KEYDB_SEARCH_MODE_SUBJECT;
954       break;
955
956     case '#':
957       { 
958         const char *si;
959         
960         s++;
961         if ( *s == '/')
962           { /* "#/" indicates an issuer's DN */
963             s++;
964             if (!*s || spacep (*s))
965               return 0; /* no DN or prefixed with a space */
966             desc->u.name = s;
967             mode = KEYDB_SEARCH_MODE_ISSUER;
968           }
969         else 
970           { /* serialnumber + optional issuer ID */
971             for (si=s; *si && *si != '/'; si++)
972               {
973                 if (!strchr("01234567890abcdefABCDEF", *si))
974                   return 0; /* invalid digit in serial number*/
975               }
976             desc->sn = s;
977             desc->sn_is_string = 1;
978             if (!*si)
979               mode = KEYDB_SEARCH_MODE_SN;
980             else
981               {
982                 s = si+1;
983                 if (!*s || spacep (*s))
984                   return 0; /* no DN or prefixed with a space */
985                 desc->u.name = s;
986                 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
987               }
988           }
989       }
990       break;
991
992     case ':': /*Unified fingerprint */
993       {  
994         const char *se, *si;
995         int i;
996         
997         se = strchr (++s,':');
998         if (!se)
999           return 0;
1000         for (i=0,si=s; si < se; si++, i++ )
1001           {
1002             if (!strchr("01234567890abcdefABCDEF", *si))
1003               return 0; /* invalid digit */
1004           }
1005         if (i != 32 && i != 40)
1006           return 0; /* invalid length of fpr*/
1007         for (i=0,si=s; si < se; i++, si +=2) 
1008           desc->u.fpr[i] = hextobyte(si);
1009         for (; i < 20; i++)
1010           desc->u.fpr[i]= 0;
1011         s = se + 1;
1012         mode = KEYDB_SEARCH_MODE_FPR;
1013       } 
1014       break;
1015            
1016     default:
1017       if (s[0] == '0' && s[1] == 'x')
1018         {
1019           hexprefix = 1;
1020           s += 2;
1021         }
1022
1023       hexlength = strspn(s, "0123456789abcdefABCDEF");
1024       if (hexlength >= 8 && s[hexlength] =='!')
1025         {
1026           *force_exact = 1;
1027           hexlength++; /* just for the following check */
1028         }
1029       
1030       /* check if a hexadecimal number is terminated by EOS or blank */
1031       if (hexlength && s[hexlength] && !spacep(s[hexlength])) 
1032         {
1033           if (hexprefix) /* a "0x" prefix without correct */
1034             return 0;    /* termination is an error */
1035           /* The first chars looked like a hex number, but really is
1036              not */
1037           hexlength = 0;  
1038         }
1039       
1040       if (*force_exact)
1041         hexlength--; /* remove the bang */
1042
1043       if (hexlength == 8
1044           || (!hexprefix && hexlength == 9 && *s == '0'))
1045         { /* short keyid */
1046           unsigned long kid;
1047           if (hexlength == 9)
1048             s++;
1049           kid = strtoul( s, NULL, 16 );
1050           desc->u.kid[4] = kid >> 24; 
1051           desc->u.kid[5] = kid >> 16; 
1052           desc->u.kid[6] = kid >>  8; 
1053           desc->u.kid[7] = kid; 
1054           mode = KEYDB_SEARCH_MODE_SHORT_KID;
1055         }
1056       else if (hexlength == 16
1057                || (!hexprefix && hexlength == 17 && *s == '0'))
1058         { /* complete keyid */
1059           unsigned long kid0, kid1;
1060           char buf[9];
1061           if (hexlength == 17)
1062             s++;
1063           mem2str(buf, s, 9 );
1064           kid0 = strtoul (buf, NULL, 16);
1065           kid1 = strtoul (s+8, NULL, 16);
1066           desc->u.kid[0] = kid0 >> 24; 
1067           desc->u.kid[1] = kid0 >> 16; 
1068           desc->u.kid[2] = kid0 >>  8; 
1069           desc->u.kid[3] = kid0; 
1070           desc->u.kid[4] = kid1 >> 24; 
1071           desc->u.kid[5] = kid1 >> 16; 
1072           desc->u.kid[6] = kid1 >>  8; 
1073           desc->u.kid[7] = kid1; 
1074           mode = KEYDB_SEARCH_MODE_LONG_KID;
1075         }
1076       else if (hexlength == 32
1077                || (!hexprefix && hexlength == 33 && *s == '0'))
1078         { /* md5 fingerprint */
1079           int i;
1080           if (hexlength == 33)
1081             s++;
1082           memset(desc->u.fpr+16, 0, 4); 
1083           for (i=0; i < 16; i++, s+=2) 
1084             {
1085               int c = hextobyte(s);
1086               if (c == -1)
1087                 return 0;
1088               desc->u.fpr[i] = c;
1089             }
1090           mode = KEYDB_SEARCH_MODE_FPR16;
1091         }
1092       else if (hexlength == 40
1093                || (!hexprefix && hexlength == 41 && *s == '0'))
1094         { /* sha1/rmd160 fingerprint */
1095           int i;
1096           if (hexlength == 41)
1097             s++;
1098           for (i=0; i < 20; i++, s+=2) 
1099             {
1100               int c = hextobyte(s);
1101               if (c == -1)
1102                 return 0;
1103               desc->u.fpr[i] = c;
1104             }
1105           mode = KEYDB_SEARCH_MODE_FPR20;
1106         }
1107       else if (!hexprefix)
1108         { /* default is substring search */
1109           *force_exact = 0;
1110           desc->u.name = s;
1111           mode = KEYDB_SEARCH_MODE_SUBSTR; 
1112         }
1113       else
1114         { /* hex number with a prefix but a wrong length */
1115           return 0;
1116         }
1117     }
1118   
1119   desc->mode = mode;
1120   return mode;
1121 }
1122
1123
1124 int
1125 keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
1126 {
1127   int dummy;
1128   KEYDB_SEARCH_DESC dummy_desc;
1129
1130   if (!desc)
1131     desc = &dummy_desc;
1132
1133   if (!classify_user_id (name, desc, &dummy))
1134     return GNUPG_Invalid_Name;
1135   return 0;
1136 }
1137