* base64.c (base64_reader_cb): Try to detect an S/MIME body part.
[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, KsbaConstSexp serial)
838 {
839   KEYDB_SEARCH_DESC desc;
840   int rc;
841   const unsigned char *s;
842   
843   memset (&desc, 0, sizeof desc);
844   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
845   s = serial;
846   if (*s !='(')
847     return GNUPG_Invalid_Value;
848   s++;
849   for (desc.snlen = 0; digitp (s); s++)
850     desc.snlen = 10*desc.snlen + atoi_1 (s);
851   if (*s !=':')
852     return GNUPG_Invalid_Value;
853   desc.sn = s+1;
854   desc.u.name = issuer;
855   rc = keydb_search (hd, &desc, 1);
856   return rc;
857 }
858
859 int
860 keydb_search_subject (KEYDB_HANDLE hd, const char *name)
861 {
862   KEYDB_SEARCH_DESC desc;
863   int rc;
864   
865   memset (&desc, 0, sizeof desc);
866   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
867   desc.u.name = name;
868   rc = keydb_search (hd, &desc, 1);
869   return rc;
870 }
871
872
873 static int
874 hextobyte (const unsigned char *s)
875 {
876   int c;
877
878   if( *s >= '0' && *s <= '9' )
879     c = 16 * (*s - '0');
880   else if ( *s >= 'A' && *s <= 'F' )
881     c = 16 * (10 + *s - 'A');
882   else if ( *s >= 'a' && *s <= 'f' )
883     c = 16 * (10 + *s - 'a');
884   else
885     return -1;
886   s++;
887   if ( *s >= '0' && *s <= '9' )
888     c += *s - '0';
889   else if ( *s >= 'A' && *s <= 'F' )
890     c += 10 + *s - 'A';
891   else if ( *s >= 'a' && *s <= 'f' )
892     c += 10 + *s - 'a';
893   else
894     return -1;
895   return c;
896 }
897
898
899 static int
900 classify_user_id (const char *name, 
901                   KEYDB_SEARCH_DESC *desc,
902                   int *force_exact )
903 {
904   const char *s;
905   int hexprefix = 0;
906   int hexlength;
907   int mode = 0;   
908     
909   /* clear the structure so that the mode field is set to zero unless
910    * we set it to the correct value right at the end of this function */
911   memset (desc, 0, sizeof *desc);
912   *force_exact = 0;
913   /* skip leading spaces.  Fixme: what about trailing white space? */
914   for(s = name; *s && spacep(*s); s++ )
915     ;
916
917   switch (*s) 
918     {
919     case 0:  /* empty string is an error */
920       return 0;
921
922     case '.': /* an email address, compare from end */
923       mode = KEYDB_SEARCH_MODE_MAILEND;
924       s++;
925       desc->u.name = s;
926       break;
927
928     case '<': /* an email address */
929       mode = KEYDB_SEARCH_MODE_MAIL;
930       s++;
931       desc->u.name = s;
932       break;
933
934     case '@':  /* part of an email address */
935       mode = KEYDB_SEARCH_MODE_MAILSUB;
936       s++;
937       desc->u.name = s;
938       break;
939
940     case '=':  /* exact compare */
941       mode = KEYDB_SEARCH_MODE_EXACT;
942       s++;
943       desc->u.name = s;
944       break;
945
946     case '*':  /* case insensitive substring search */
947       mode = KEYDB_SEARCH_MODE_SUBSTR;
948       s++;
949       desc->u.name = s;
950       break;
951
952     case '+':  /* compare individual words */
953       mode = KEYDB_SEARCH_MODE_WORDS;
954       s++;
955       desc->u.name = s;
956       break;
957
958     case '/': /* subject's DN */
959       s++;
960       if (!*s || spacep (*s))
961         return 0; /* no DN or prefixed with a space */
962       desc->u.name = s;
963       mode = KEYDB_SEARCH_MODE_SUBJECT;
964       break;
965
966     case '#':
967       { 
968         const char *si;
969         
970         s++;
971         if ( *s == '/')
972           { /* "#/" indicates an issuer's DN */
973             s++;
974             if (!*s || spacep (*s))
975               return 0; /* no DN or prefixed with a space */
976             desc->u.name = s;
977             mode = KEYDB_SEARCH_MODE_ISSUER;
978           }
979         else 
980           { /* serialnumber + optional issuer ID */
981             for (si=s; *si && *si != '/'; si++)
982               {
983                 if (!strchr("01234567890abcdefABCDEF", *si))
984                   return 0; /* invalid digit in serial number*/
985               }
986             desc->sn = s;
987             desc->snlen = -1;
988             if (!*si)
989               mode = KEYDB_SEARCH_MODE_SN;
990             else
991               {
992                 s = si+1;
993                 if (!*s || spacep (*s))
994                   return 0; /* no DN or prefixed with a space */
995                 desc->u.name = s;
996                 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
997               }
998           }
999       }
1000       break;
1001
1002     case ':': /*Unified fingerprint */
1003       {  
1004         const char *se, *si;
1005         int i;
1006         
1007         se = strchr (++s,':');
1008         if (!se)
1009           return 0;
1010         for (i=0,si=s; si < se; si++, i++ )
1011           {
1012             if (!strchr("01234567890abcdefABCDEF", *si))
1013               return 0; /* invalid digit */
1014           }
1015         if (i != 32 && i != 40)
1016           return 0; /* invalid length of fpr*/
1017         for (i=0,si=s; si < se; i++, si +=2) 
1018           desc->u.fpr[i] = hextobyte(si);
1019         for (; i < 20; i++)
1020           desc->u.fpr[i]= 0;
1021         s = se + 1;
1022         mode = KEYDB_SEARCH_MODE_FPR;
1023       } 
1024       break;
1025            
1026     default:
1027       if (s[0] == '0' && s[1] == 'x')
1028         {
1029           hexprefix = 1;
1030           s += 2;
1031         }
1032
1033       hexlength = strspn(s, "0123456789abcdefABCDEF");
1034       if (hexlength >= 8 && s[hexlength] =='!')
1035         {
1036           *force_exact = 1;
1037           hexlength++; /* just for the following check */
1038         }
1039       
1040       /* check if a hexadecimal number is terminated by EOS or blank */
1041       if (hexlength && s[hexlength] && !spacep(s[hexlength])) 
1042         {
1043           if (hexprefix) /* a "0x" prefix without correct */
1044             return 0;    /* termination is an error */
1045           /* The first chars looked like a hex number, but really is
1046              not */
1047           hexlength = 0;  
1048         }
1049       
1050       if (*force_exact)
1051         hexlength--; /* remove the bang */
1052
1053       if (hexlength == 8
1054           || (!hexprefix && hexlength == 9 && *s == '0'))
1055         { /* short keyid */
1056           unsigned long kid;
1057           if (hexlength == 9)
1058             s++;
1059           kid = strtoul( s, NULL, 16 );
1060           desc->u.kid[4] = kid >> 24; 
1061           desc->u.kid[5] = kid >> 16; 
1062           desc->u.kid[6] = kid >>  8; 
1063           desc->u.kid[7] = kid; 
1064           mode = KEYDB_SEARCH_MODE_SHORT_KID;
1065         }
1066       else if (hexlength == 16
1067                || (!hexprefix && hexlength == 17 && *s == '0'))
1068         { /* complete keyid */
1069           unsigned long kid0, kid1;
1070           char buf[9];
1071           if (hexlength == 17)
1072             s++;
1073           mem2str(buf, s, 9 );
1074           kid0 = strtoul (buf, NULL, 16);
1075           kid1 = strtoul (s+8, NULL, 16);
1076           desc->u.kid[0] = kid0 >> 24; 
1077           desc->u.kid[1] = kid0 >> 16; 
1078           desc->u.kid[2] = kid0 >>  8; 
1079           desc->u.kid[3] = kid0; 
1080           desc->u.kid[4] = kid1 >> 24; 
1081           desc->u.kid[5] = kid1 >> 16; 
1082           desc->u.kid[6] = kid1 >>  8; 
1083           desc->u.kid[7] = kid1; 
1084           mode = KEYDB_SEARCH_MODE_LONG_KID;
1085         }
1086       else if (hexlength == 32
1087                || (!hexprefix && hexlength == 33 && *s == '0'))
1088         { /* md5 fingerprint */
1089           int i;
1090           if (hexlength == 33)
1091             s++;
1092           memset(desc->u.fpr+16, 0, 4); 
1093           for (i=0; i < 16; i++, s+=2) 
1094             {
1095               int c = hextobyte(s);
1096               if (c == -1)
1097                 return 0;
1098               desc->u.fpr[i] = c;
1099             }
1100           mode = KEYDB_SEARCH_MODE_FPR16;
1101         }
1102       else if (hexlength == 40
1103                || (!hexprefix && hexlength == 41 && *s == '0'))
1104         { /* sha1/rmd160 fingerprint */
1105           int i;
1106           if (hexlength == 41)
1107             s++;
1108           for (i=0; i < 20; i++, s+=2) 
1109             {
1110               int c = hextobyte(s);
1111               if (c == -1)
1112                 return 0;
1113               desc->u.fpr[i] = c;
1114             }
1115           mode = KEYDB_SEARCH_MODE_FPR20;
1116         }
1117       else if (!hexprefix)
1118         { /* default is substring search */
1119           *force_exact = 0;
1120           desc->u.name = s;
1121           mode = KEYDB_SEARCH_MODE_SUBSTR; 
1122         }
1123       else
1124         { /* hex number with a prefix but a wrong length */
1125           return 0;
1126         }
1127     }
1128   
1129   desc->mode = mode;
1130   return mode;
1131 }
1132
1133
1134 int
1135 keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
1136 {
1137   int dummy;
1138   KEYDB_SEARCH_DESC dummy_desc;
1139
1140   if (!desc)
1141     desc = &dummy_desc;
1142
1143   if (!classify_user_id (name, desc, &dummy))
1144     return GNUPG_Invalid_Name;
1145   return 0;
1146 }
1147