* keydb.c (keydb_add_resource): Register a lock file.
[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 static int active_handles;
39
40 typedef enum {
41     KEYDB_RESOURCE_TYPE_NONE = 0,
42     KEYDB_RESOURCE_TYPE_KEYBOX
43 } KeydbResourceType;
44 #define MAX_KEYDB_RESOURCES 20
45
46 struct resource_item {
47   KeydbResourceType type;
48   union {
49     KEYBOX_HANDLE kr;
50   } u;
51   void *token;
52   int secret;
53   DOTLOCK lockhandle;
54 };
55
56 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
57 static int used_resources;
58
59 struct keydb_handle {
60   int locked;
61   int found;
62   int current;
63   int is_ephemeral;
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 register the file */
201         {
202           
203           void *token = keybox_register_file (filename, secret);
204           if (!token)
205             ; /* already registered - ignore it */
206           else if (used_resources >= MAX_KEYDB_RESOURCES)
207             rc = GNUPG_Resource_Limit;
208           else 
209             {
210               all_resources[used_resources].type = rt;
211               all_resources[used_resources].u.kr = NULL; /* Not used here */
212               all_resources[used_resources].token = token;
213               all_resources[used_resources].secret = secret;
214
215               all_resources[used_resources].lockhandle
216                 = create_dotlock (filename);
217               if (!all_resources[used_resources].lockhandle)
218                 log_fatal ( _("can't create lock for `%s'\n"), filename);
219                   
220               used_resources++;
221             }
222         }
223         break;
224     default:
225       log_error ("resource type of `%s' not supported\n", url);
226       rc = GNUPG_Not_Supported;
227       goto leave;
228     }
229
230   /* fixme: check directory permissions and print a warning */
231
232  leave:
233   if (rc)
234     log_error ("keyblock resource `%s': %s\n", filename, gnupg_strerror(rc));
235   else if (secret)
236     any_secret = 1;
237   else
238     any_public = 1;
239   xfree (filename);
240   return rc;
241 }
242
243
244 KEYDB_HANDLE
245 keydb_new (int secret)
246 {
247   KEYDB_HANDLE hd;
248   int i, j;
249   
250   hd = xcalloc (1, sizeof *hd);
251   hd->found = -1;
252   
253   assert (used_resources <= MAX_KEYDB_RESOURCES);
254   for (i=j=0; i < used_resources; i++)
255     {
256       if (!all_resources[i].secret != !secret)
257         continue;
258       switch (all_resources[i].type)
259         {
260         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
261           break;
262         case KEYDB_RESOURCE_TYPE_KEYBOX:
263           hd->active[j].type   = all_resources[i].type;
264           hd->active[j].token  = all_resources[i].token;
265           hd->active[j].secret = all_resources[i].secret;
266           hd->active[j].lockhandle = all_resources[i].lockhandle;
267           hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
268           if (!hd->active[j].u.kr) 
269             {
270               xfree (hd);
271               return NULL; /* fixme: release all previously allocated handles*/
272             }
273           j++;
274           break;
275         }
276     }
277   hd->used = j;
278   
279   active_handles++;
280   return hd;
281 }
282
283 void 
284 keydb_release (KEYDB_HANDLE hd)
285 {
286   int i;
287   
288   if (!hd)
289     return;
290   assert (active_handles > 0);
291   active_handles--;
292
293   unlock_all (hd);
294   for (i=0; i < hd->used; i++)
295     {
296       switch (hd->active[i].type) 
297         {
298         case KEYDB_RESOURCE_TYPE_NONE:
299           break;
300         case KEYDB_RESOURCE_TYPE_KEYBOX:
301           keybox_release (hd->active[i].u.kr);
302           break;
303         }
304     }
305
306     xfree (hd);
307 }
308
309
310 /* Return the name of the current resource.  This is function first
311    looks for the last found found, then for the current search
312    position, and last returns the first available resource.  The
313    returned string is only valid as long as the handle exists.  This
314    function does only return NULL if no handle is specified, in all
315    other error cases an empty string is returned.  */
316 const char *
317 keydb_get_resource_name (KEYDB_HANDLE hd)
318 {
319   int idx;
320   const char *s = NULL;
321   
322   if (!hd) 
323     return NULL;
324
325   if ( hd->found >= 0 && hd->found < hd->used) 
326     idx = hd->found;
327   else if ( hd->current >= 0 && hd->current < hd->used) 
328     idx = hd->current;
329   else
330     idx = 0;
331
332   switch (hd->active[idx].type) 
333     {
334     case KEYDB_RESOURCE_TYPE_NONE:
335       s = NULL; 
336       break;
337     case KEYDB_RESOURCE_TYPE_KEYBOX:
338       s = keybox_get_resource_name (hd->active[idx].u.kr);
339       break;
340     }
341   
342   return s? s: "";
343 }
344
345 /* Switch the handle into ephemeral mode and return the orginal value. */
346 int
347 keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
348 {
349   int i;
350
351   if (!hd)
352     return 0;
353
354   yes = !!yes;
355   if (hd->is_ephemeral != yes)
356     {
357       for (i=0; i < hd->used; i++)
358         {
359           switch (hd->active[i].type) 
360             {
361             case KEYDB_RESOURCE_TYPE_NONE:
362               break;
363             case KEYDB_RESOURCE_TYPE_KEYBOX:
364               keybox_set_ephemeral (hd->active[i].u.kr, yes);
365               break;
366             }
367         }
368     }
369       
370   i = hd->is_ephemeral;
371   hd->is_ephemeral = yes;
372   return i;
373 }
374
375
376 \f
377 static int 
378 lock_all (KEYDB_HANDLE hd)
379 {
380   int i, rc = 0;
381
382   /* Fixme: This locking scheme may lead to deadlock if the resources
383      are not added in the same sequence by all processes.  We are
384      cuurently only allowing one resource so it is not a problem. */
385   for (i=0; i < hd->used; i++) 
386     {
387       switch (hd->active[i].type) 
388         {
389         case KEYDB_RESOURCE_TYPE_NONE:
390           break;
391         case KEYDB_RESOURCE_TYPE_KEYBOX:
392           if (hd->active[i].lockhandle)
393             rc = make_dotlock (hd->active[i].lockhandle, -1);
394           break;
395         }
396       if (rc)
397         break;
398     }
399
400     if (rc) 
401       {
402         /* revert the already set locks */
403         for (i--; i >= 0; i--) 
404           {
405             switch (hd->active[i].type) 
406               {
407               case KEYDB_RESOURCE_TYPE_NONE:
408                 break;
409               case KEYDB_RESOURCE_TYPE_KEYBOX:
410                 if (hd->active[i].lockhandle)
411                   release_dotlock (hd->active[i].lockhandle);
412                 break;
413               }
414           }
415       }
416     else
417       hd->locked = 1;
418
419     return rc;
420 }
421
422 static void
423 unlock_all (KEYDB_HANDLE hd)
424 {
425   int i;
426   
427   if (!hd->locked)
428     return;
429
430   for (i=hd->used-1; i >= 0; i--) 
431     {
432       switch (hd->active[i].type) 
433         {
434         case KEYDB_RESOURCE_TYPE_NONE:
435           break;
436         case KEYDB_RESOURCE_TYPE_KEYBOX:
437           if (hd->active[i].lockhandle)
438             release_dotlock (hd->active[i].lockhandle);
439           break;
440         }
441     }
442   hd->locked = 0;
443 }
444
445 \f
446 #if 0
447 /*
448  * Return the last found keybox.  Caller must free it.
449  * The returned keyblock has the kbode flag bit 0 set for the node with
450  * the public key used to locate the keyblock or flag bit 1 set for 
451  * the user ID node.
452  */
453 int
454 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
455 {
456     int rc = 0;
457
458     if (!hd)
459         return G10ERR_INV_ARG;
460
461     if ( hd->found < 0 || hd->found >= hd->used) 
462         return -1; /* nothing found */
463
464     switch (hd->active[hd->found].type) {
465       case KEYDB_RESOURCE_TYPE_NONE:
466         rc = G10ERR_GENERAL; /* oops */
467         break;
468       case KEYDB_RESOURCE_TYPE_KEYBOX:
469         rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
470         break;
471     }
472
473     return rc;
474 }
475
476 /* 
477  * update the current keyblock with KB
478  */
479 int
480 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
481 {
482     int rc = 0;
483
484     if (!hd)
485         return G10ERR_INV_ARG;
486
487     if ( hd->found < 0 || hd->found >= hd->used) 
488         return -1; /* nothing found */
489
490     if( opt.dry_run )
491         return 0;
492
493     rc = lock_all (hd);
494     if (rc)
495         return rc;
496
497     switch (hd->active[hd->found].type) {
498       case KEYDB_RESOURCE_TYPE_NONE:
499         rc = G10ERR_GENERAL; /* oops */
500         break;
501       case KEYDB_RESOURCE_TYPE_KEYBOX:
502         rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
503         break;
504     }
505
506     unlock_all (hd);
507     return rc;
508 }
509
510
511 /* 
512  * Insert a new KB into one of the resources. 
513  */
514 int
515 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
516 {
517     int rc = -1;
518     int idx;
519
520     if (!hd) 
521         return G10ERR_INV_ARG;
522
523     if( opt.dry_run )
524         return 0;
525
526     if ( hd->found >= 0 && hd->found < hd->used) 
527         idx = hd->found;
528     else if ( hd->current >= 0 && hd->current < hd->used) 
529         idx = hd->current;
530     else
531         return G10ERR_GENERAL;
532
533     rc = lock_all (hd);
534     if (rc)
535         return rc;
536
537     switch (hd->active[idx].type) {
538       case KEYDB_RESOURCE_TYPE_NONE:
539         rc = G10ERR_GENERAL; /* oops */
540         break;
541       case KEYDB_RESOURCE_TYPE_KEYBOX:
542         rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
543         break;
544     }
545
546     unlock_all (hd);
547     return rc;
548 }
549
550 #endif /*disabled code*/
551
552
553 \f
554 /*
555   Return the last found keybox.  Caller must free it.  The returned
556   keyblock has the kbode flag bit 0 set for the node with the public
557   key used to locate the keyblock or flag bit 1 set for the user ID
558   node.  */
559 int
560 keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert)
561 {
562   int rc = 0;
563
564   if (!hd)
565     return GNUPG_Invalid_Value;
566   
567   if ( hd->found < 0 || hd->found >= hd->used) 
568     return -1; /* nothing found */
569   
570   switch (hd->active[hd->found].type) 
571     {
572     case KEYDB_RESOURCE_TYPE_NONE:
573       rc = GNUPG_General_Error; /* oops */
574       break;
575     case KEYDB_RESOURCE_TYPE_KEYBOX:
576       rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
577       break;
578     }
579   
580   return rc;
581 }
582
583 /* 
584  * Insert a new Certificate into one of the resources. 
585  */
586 int
587 keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert)
588 {
589   int rc = -1;
590   int idx;
591   char digest[20];
592   
593   if (!hd) 
594     return GNUPG_Invalid_Value;
595
596   if (opt.dry_run)
597     return 0;
598   
599   if ( hd->found >= 0 && hd->found < hd->used) 
600     idx = hd->found;
601   else if ( hd->current >= 0 && hd->current < hd->used) 
602     idx = hd->current;
603   else
604     return GNUPG_General_Error;
605
606   rc = lock_all (hd);
607   if (rc)
608     return rc;
609
610   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
611
612   switch (hd->active[idx].type) 
613     {
614     case KEYDB_RESOURCE_TYPE_NONE:
615       rc = GNUPG_General_Error;
616       break;
617     case KEYDB_RESOURCE_TYPE_KEYBOX:
618       rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
619       break;
620     }
621   
622   unlock_all (hd);
623   return rc;
624 }
625
626
627
628 /* update the current keyblock with KB */
629 int
630 keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert)
631 {
632   int rc = 0;
633   char digest[20];
634   
635   if (!hd)
636     return GNUPG_Invalid_Value;
637
638   if ( hd->found < 0 || hd->found >= hd->used) 
639     return -1; /* nothing found */
640
641   if (opt.dry_run)
642     return 0;
643
644   rc = lock_all (hd);
645   if (rc)
646     return rc;
647
648   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
649
650   switch (hd->active[hd->found].type) 
651     {
652     case KEYDB_RESOURCE_TYPE_NONE:
653       rc = GNUPG_General_Error; /* oops */
654       break;
655     case KEYDB_RESOURCE_TYPE_KEYBOX:
656       rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
657       break;
658     }
659
660   unlock_all (hd);
661   return rc;
662 }
663
664
665 /* 
666  * The current keyblock or cert will be deleted.
667  */
668 int
669 keydb_delete (KEYDB_HANDLE hd)
670 {
671   int rc = -1;
672   
673   if (!hd)
674     return GNUPG_Invalid_Value;
675
676   if ( hd->found < 0 || hd->found >= hd->used) 
677     return -1; /* nothing found */
678
679   if( opt.dry_run )
680     return 0;
681
682   rc = lock_all (hd);
683   if (rc)
684     return rc;
685
686   switch (hd->active[hd->found].type)
687     {
688     case KEYDB_RESOURCE_TYPE_NONE:
689       rc = GNUPG_General_Error;
690       break;
691     case KEYDB_RESOURCE_TYPE_KEYBOX:
692       rc = keybox_delete (hd->active[hd->found].u.kr);
693       break;
694     }
695
696   unlock_all (hd);
697   return rc;
698 }
699
700
701 \f
702 /*
703  * Locate the default writable key resource, so that the next
704  * operation (which is only relevant for inserts) will be done on this
705  * resource.  
706  */
707 int
708 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
709 {
710   int rc;
711   
712   if (!hd)
713     return GNUPG_Invalid_Value;
714   
715   rc = keydb_search_reset (hd); /* this does reset hd->current */
716   if (rc)
717     return rc;
718   
719   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) 
720     {
721       switch (hd->active[hd->current].type) 
722         {
723         case KEYDB_RESOURCE_TYPE_NONE:
724           BUG();
725           break;
726         case KEYDB_RESOURCE_TYPE_KEYBOX:
727           if (keybox_is_writable (hd->active[hd->current].token))
728             return 0; /* found (hd->current is set to it) */
729           break;
730         }
731     }
732   
733   return -1;
734 }
735
736 /*
737  * Rebuild the caches of all key resources.
738  */
739 void
740 keydb_rebuild_caches (void)
741 {
742   int i;
743   
744   for (i=0; i < used_resources; i++)
745     {
746       if (all_resources[i].secret)
747         continue;
748       switch (all_resources[i].type)
749         {
750         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
751           break;
752         case KEYDB_RESOURCE_TYPE_KEYBOX:
753 /*            rc = keybox_rebuild_cache (all_resources[i].token); */
754 /*            if (rc) */
755 /*              log_error (_("failed to rebuild keybox cache: %s\n"), */
756 /*                         g10_errstr (rc)); */
757           break;
758         }
759     }
760 }
761
762
763
764 /* 
765  * Start the next search on this handle right at the beginning
766  */
767 int 
768 keydb_search_reset (KEYDB_HANDLE hd)
769 {
770   int i, rc = 0;
771   
772   if (!hd)
773     return GNUPG_Invalid_Value;
774
775   hd->current = 0; 
776   hd->found = -1;
777   /* and reset all resources */
778   for (i=0; !rc && i < hd->used; i++) 
779     {
780       switch (hd->active[i].type) 
781         {
782         case KEYDB_RESOURCE_TYPE_NONE:
783           break;
784         case KEYDB_RESOURCE_TYPE_KEYBOX:
785           rc = keybox_search_reset (hd->active[i].u.kr);
786           break;
787         }
788     }
789   return rc; /* fixme: we need to map error codes or share them with
790                 all modules*/
791 }
792
793 /* 
794  * Search through all keydb resources, starting at the current position,
795  * for a keyblock which contains one of the keys described in the DESC array.
796  */
797 int 
798 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
799 {
800   int rc = -1;
801   
802   if (!hd)
803     return GNUPG_Invalid_Value;
804
805   while (rc == -1 && hd->current >= 0 && hd->current < hd->used) 
806     {
807       switch (hd->active[hd->current].type) 
808         {
809         case KEYDB_RESOURCE_TYPE_NONE:
810           BUG(); /* we should never see it here */
811           break;
812         case KEYDB_RESOURCE_TYPE_KEYBOX:
813           rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
814           break;
815         }
816       if (rc == -1) /* EOF -> switch to next resource */
817         hd->current++; 
818       else if (!rc)
819         hd->found = hd->current;
820     }
821   
822   return rc; 
823 }
824
825
826 int
827 keydb_search_first (KEYDB_HANDLE hd)
828 {
829   KEYDB_SEARCH_DESC desc;
830   
831   memset (&desc, 0, sizeof desc);
832   desc.mode = KEYDB_SEARCH_MODE_FIRST;
833   return keydb_search (hd, &desc, 1);
834 }
835
836 int
837 keydb_search_next (KEYDB_HANDLE hd)
838 {
839   KEYDB_SEARCH_DESC desc;
840   
841   memset (&desc, 0, sizeof desc);
842   desc.mode = KEYDB_SEARCH_MODE_NEXT;
843   return keydb_search (hd, &desc, 1);
844 }
845
846 int
847 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
848 {
849   KEYDB_SEARCH_DESC desc;
850   
851   memset (&desc, 0, sizeof desc);
852   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
853 /*    desc.u.kid[0] = kid[0]; */
854 /*    desc.u.kid[1] = kid[1]; */
855   return keydb_search (hd, &desc, 1);
856 }
857
858 int
859 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
860 {
861   KEYDB_SEARCH_DESC desc;
862   
863   memset (&desc, 0, sizeof desc);
864   desc.mode = KEYDB_SEARCH_MODE_FPR;
865   memcpy (desc.u.fpr, fpr, 20);
866   return keydb_search (hd, &desc, 1);
867 }
868
869 int
870 keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
871 {
872   KEYDB_SEARCH_DESC desc;
873   int rc;
874   
875   memset (&desc, 0, sizeof desc);
876   desc.mode = KEYDB_SEARCH_MODE_ISSUER;
877   desc.u.name = issuer;
878   rc = keydb_search (hd, &desc, 1);
879   return rc;
880 }
881
882 int
883 keydb_search_issuer_sn (KEYDB_HANDLE hd,
884                         const char *issuer, KsbaConstSexp serial)
885 {
886   KEYDB_SEARCH_DESC desc;
887   int rc;
888   const unsigned char *s;
889   
890   memset (&desc, 0, sizeof desc);
891   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
892   s = serial;
893   if (*s !='(')
894     return GNUPG_Invalid_Value;
895   s++;
896   for (desc.snlen = 0; digitp (s); s++)
897     desc.snlen = 10*desc.snlen + atoi_1 (s);
898   if (*s !=':')
899     return GNUPG_Invalid_Value;
900   desc.sn = s+1;
901   desc.u.name = issuer;
902   rc = keydb_search (hd, &desc, 1);
903   return rc;
904 }
905
906 int
907 keydb_search_subject (KEYDB_HANDLE hd, const char *name)
908 {
909   KEYDB_SEARCH_DESC desc;
910   int rc;
911   
912   memset (&desc, 0, sizeof desc);
913   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
914   desc.u.name = name;
915   rc = keydb_search (hd, &desc, 1);
916   return rc;
917 }
918
919
920 static int
921 hextobyte (const unsigned char *s)
922 {
923   int c;
924
925   if( *s >= '0' && *s <= '9' )
926     c = 16 * (*s - '0');
927   else if ( *s >= 'A' && *s <= 'F' )
928     c = 16 * (10 + *s - 'A');
929   else if ( *s >= 'a' && *s <= 'f' )
930     c = 16 * (10 + *s - 'a');
931   else
932     return -1;
933   s++;
934   if ( *s >= '0' && *s <= '9' )
935     c += *s - '0';
936   else if ( *s >= 'A' && *s <= 'F' )
937     c += 10 + *s - 'A';
938   else if ( *s >= 'a' && *s <= 'f' )
939     c += 10 + *s - 'a';
940   else
941     return -1;
942   return c;
943 }
944
945
946 static int
947 classify_user_id (const char *name, 
948                   KEYDB_SEARCH_DESC *desc,
949                   int *force_exact )
950 {
951   const char *s;
952   int hexprefix = 0;
953   int hexlength;
954   int mode = 0;   
955     
956   /* clear the structure so that the mode field is set to zero unless
957    * we set it to the correct value right at the end of this function */
958   memset (desc, 0, sizeof *desc);
959   *force_exact = 0;
960   /* skip leading spaces.  Fixme: what about trailing white space? */
961   for(s = name; *s && spacep (s); s++ )
962     ;
963
964   switch (*s) 
965     {
966     case 0:  /* empty string is an error */
967       return 0;
968
969     case '.': /* an email address, compare from end */
970       mode = KEYDB_SEARCH_MODE_MAILEND;
971       s++;
972       desc->u.name = s;
973       break;
974
975     case '<': /* an email address */
976       mode = KEYDB_SEARCH_MODE_MAIL;
977       s++;
978       desc->u.name = s;
979       break;
980
981     case '@':  /* part of an email address */
982       mode = KEYDB_SEARCH_MODE_MAILSUB;
983       s++;
984       desc->u.name = s;
985       break;
986
987     case '=':  /* exact compare */
988       mode = KEYDB_SEARCH_MODE_EXACT;
989       s++;
990       desc->u.name = s;
991       break;
992
993     case '*':  /* case insensitive substring search */
994       mode = KEYDB_SEARCH_MODE_SUBSTR;
995       s++;
996       desc->u.name = s;
997       break;
998
999     case '+':  /* compare individual words */
1000       mode = KEYDB_SEARCH_MODE_WORDS;
1001       s++;
1002       desc->u.name = s;
1003       break;
1004
1005     case '/': /* subject's DN */
1006       s++;
1007       if (!*s || spacep (s))
1008         return 0; /* no DN or prefixed with a space */
1009       desc->u.name = s;
1010       mode = KEYDB_SEARCH_MODE_SUBJECT;
1011       break;
1012
1013     case '#':
1014       { 
1015         const char *si;
1016         
1017         s++;
1018         if ( *s == '/')
1019           { /* "#/" indicates an issuer's DN */
1020             s++;
1021             if (!*s || spacep (s))
1022               return 0; /* no DN or prefixed with a space */
1023             desc->u.name = s;
1024             mode = KEYDB_SEARCH_MODE_ISSUER;
1025           }
1026         else 
1027           { /* serialnumber + optional issuer ID */
1028             for (si=s; *si && *si != '/'; si++)
1029               {
1030                 if (!strchr("01234567890abcdefABCDEF", *si))
1031                   return 0; /* invalid digit in serial number*/
1032               }
1033             desc->sn = s;
1034             desc->snlen = -1;
1035             if (!*si)
1036               mode = KEYDB_SEARCH_MODE_SN;
1037             else
1038               {
1039                 s = si+1;
1040                 if (!*s || spacep (s))
1041                   return 0; /* no DN or prefixed with a space */
1042                 desc->u.name = s;
1043                 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
1044               }
1045           }
1046       }
1047       break;
1048
1049     case ':': /*Unified fingerprint */
1050       {  
1051         const char *se, *si;
1052         int i;
1053         
1054         se = strchr (++s,':');
1055         if (!se)
1056           return 0;
1057         for (i=0,si=s; si < se; si++, i++ )
1058           {
1059             if (!strchr("01234567890abcdefABCDEF", *si))
1060               return 0; /* invalid digit */
1061           }
1062         if (i != 32 && i != 40)
1063           return 0; /* invalid length of fpr*/
1064         for (i=0,si=s; si < se; i++, si +=2) 
1065           desc->u.fpr[i] = hextobyte(si);
1066         for (; i < 20; i++)
1067           desc->u.fpr[i]= 0;
1068         s = se + 1;
1069         mode = KEYDB_SEARCH_MODE_FPR;
1070       } 
1071       break;
1072            
1073     default:
1074       if (s[0] == '0' && s[1] == 'x')
1075         {
1076           hexprefix = 1;
1077           s += 2;
1078         }
1079
1080       hexlength = strspn(s, "0123456789abcdefABCDEF");
1081       if (hexlength >= 8 && s[hexlength] =='!')
1082         {
1083           *force_exact = 1;
1084           hexlength++; /* just for the following check */
1085         }
1086       
1087       /* check if a hexadecimal number is terminated by EOS or blank */
1088       if (hexlength && s[hexlength] && !spacep (s+hexlength)) 
1089         {
1090           if (hexprefix) /* a "0x" prefix without correct */
1091             return 0;    /* termination is an error */
1092           /* The first chars looked like a hex number, but really is
1093              not */
1094           hexlength = 0;  
1095         }
1096       
1097       if (*force_exact)
1098         hexlength--; /* remove the bang */
1099
1100       if (hexlength == 8
1101           || (!hexprefix && hexlength == 9 && *s == '0'))
1102         { /* short keyid */
1103           unsigned long kid;
1104           if (hexlength == 9)
1105             s++;
1106           kid = strtoul( s, NULL, 16 );
1107           desc->u.kid[4] = kid >> 24; 
1108           desc->u.kid[5] = kid >> 16; 
1109           desc->u.kid[6] = kid >>  8; 
1110           desc->u.kid[7] = kid; 
1111           mode = KEYDB_SEARCH_MODE_SHORT_KID;
1112         }
1113       else if (hexlength == 16
1114                || (!hexprefix && hexlength == 17 && *s == '0'))
1115         { /* complete keyid */
1116           unsigned long kid0, kid1;
1117           char buf[9];
1118           if (hexlength == 17)
1119             s++;
1120           mem2str(buf, s, 9 );
1121           kid0 = strtoul (buf, NULL, 16);
1122           kid1 = strtoul (s+8, NULL, 16);
1123           desc->u.kid[0] = kid0 >> 24; 
1124           desc->u.kid[1] = kid0 >> 16; 
1125           desc->u.kid[2] = kid0 >>  8; 
1126           desc->u.kid[3] = kid0; 
1127           desc->u.kid[4] = kid1 >> 24; 
1128           desc->u.kid[5] = kid1 >> 16; 
1129           desc->u.kid[6] = kid1 >>  8; 
1130           desc->u.kid[7] = kid1; 
1131           mode = KEYDB_SEARCH_MODE_LONG_KID;
1132         }
1133       else if (hexlength == 32
1134                || (!hexprefix && hexlength == 33 && *s == '0'))
1135         { /* md5 fingerprint */
1136           int i;
1137           if (hexlength == 33)
1138             s++;
1139           memset(desc->u.fpr+16, 0, 4); 
1140           for (i=0; i < 16; i++, s+=2) 
1141             {
1142               int c = hextobyte(s);
1143               if (c == -1)
1144                 return 0;
1145               desc->u.fpr[i] = c;
1146             }
1147           mode = KEYDB_SEARCH_MODE_FPR16;
1148         }
1149       else if (hexlength == 40
1150                || (!hexprefix && hexlength == 41 && *s == '0'))
1151         { /* sha1/rmd160 fingerprint */
1152           int i;
1153           if (hexlength == 41)
1154             s++;
1155           for (i=0; i < 20; i++, s+=2) 
1156             {
1157               int c = hextobyte(s);
1158               if (c == -1)
1159                 return 0;
1160               desc->u.fpr[i] = c;
1161             }
1162           mode = KEYDB_SEARCH_MODE_FPR20;
1163         }
1164       else if (!hexprefix)
1165         { 
1166           /* The fingerprint in an X.509 listing is often delimited by
1167              colons, so we try to single this case out. */
1168           mode = 0;
1169           hexlength = strspn (s, ":0123456789abcdefABCDEF");
1170           if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength))) 
1171             {
1172               int i;
1173
1174               for (i=0; i < 20; i++, s += 3) 
1175                 {
1176                   int c = hextobyte(s);
1177                   if (c == -1 || (i < 19 && s[2] != ':'))
1178                     break;
1179                   desc->u.fpr[i] = c;
1180                 }
1181               if (i == 20)
1182                 mode = KEYDB_SEARCH_MODE_FPR20;
1183             }
1184           if (!mode) /* default is substring search */
1185             { 
1186               *force_exact = 0;
1187               desc->u.name = s;
1188               mode = KEYDB_SEARCH_MODE_SUBSTR; 
1189             }
1190         }
1191       else
1192         { /* hex number with a prefix but a wrong length */
1193           return 0;
1194         }
1195     }
1196   
1197   desc->mode = mode;
1198   return mode;
1199 }
1200
1201
1202 int
1203 keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
1204 {
1205   int dummy;
1206   KEYDB_SEARCH_DESC dummy_desc;
1207
1208   if (!desc)
1209     desc = &dummy_desc;
1210
1211   if (!classify_user_id (name, desc, &dummy))
1212     return GNUPG_Invalid_Name;
1213   return 0;
1214 }
1215
1216 \f
1217 /* Store the certificate in the key DB but make sure that it does not
1218    already exists.  We do this simply by comparing the fingerprint.
1219    If EXISTED is not NULL it will be set to true if the certificate
1220    was already in the DB. */
1221 int
1222 keydb_store_cert (KsbaCert cert, int ephemeral, int *existed)
1223 {
1224   KEYDB_HANDLE kh;
1225   int rc;
1226   unsigned char fpr[20];
1227
1228   if (existed)
1229     *existed = 0;
1230
1231   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1232     {
1233       log_error (_("failed to get the fingerprint\n"));
1234       return GNUPG_General_Error;
1235     }
1236
1237   kh = keydb_new (0);
1238   if (!kh)
1239     {
1240       log_error (_("failed to allocate keyDB handle\n"));
1241       return GNUPG_Out_Of_Core;
1242     }
1243
1244   if (ephemeral)
1245     keydb_set_ephemeral (kh, 1);
1246   
1247   rc = keydb_search_fpr (kh, fpr);
1248   if (rc != -1)
1249     {
1250       keydb_release (kh);
1251       if (!rc)
1252         {
1253           if (existed)
1254             *existed = 1;
1255           return 0; /* okay */
1256         }
1257       log_error (_("problem looking for existing certificate: %s\n"),
1258                  gnupg_strerror (rc));
1259       return rc;
1260     }
1261
1262   rc = keydb_locate_writable (kh, 0);
1263   if (rc)
1264     {
1265       log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc));
1266       keydb_release (kh);
1267       return rc;
1268     }
1269
1270   rc = keydb_insert_cert (kh, cert);
1271   if (rc)
1272     {
1273       log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc));
1274       keydb_release (kh);
1275       return rc;
1276     }
1277   keydb_release (kh);               
1278   return 0;
1279 }
1280
1281
1282