* keylist.c (list_internal_keys): Renamed from gpgsm_list_keys.
[gnupg.git] / sm / certlist.c
1 /* certlist.c - build list of certificates
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 <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "gpgsm.h"
34 #include "keydb.h"
35 #include "i18n.h"
36  
37 /* Return 0 if the cert is usable for encryption.  A MODE of 0 checks
38    for signing a MODE of 1 checks for encryption, a MODE of 2 checks
39    for verification and a MODE of 3 for decryption (just for
40    debugging) */
41 static int
42 cert_usage_p (KsbaCert cert, int mode)
43 {
44   KsbaError err;
45   unsigned int use;
46
47   err = ksba_cert_get_key_usage (cert, &use);
48   if (err == KSBA_No_Data)
49     {
50       if (opt.verbose && mode < 2)
51         log_info (mode? 
52                   _("no key usage specified - accepted for encryption\n"):
53                   _("no key usage specified - accepted for signing\n"));
54       return 0;
55     }
56   if (err)
57     { 
58       log_error (_("error getting key usage information: %s\n"),
59                  ksba_strerror (err));
60       return map_ksba_err (err);
61     } 
62
63   if ((use & ((mode&1)? KSBA_KEYUSAGE_DIGITAL_SIGNATURE
64               : KSBA_KEYUSAGE_KEY_ENCIPHERMENT)))
65     return 0;
66   log_info (mode==3? _("certificate should have not been used for encryption\n"):
67             mode==2? _("certificate should have not been used for signing\n"):
68             mode==1? _("certificate is not usable for encryption\n"):
69                      _("certificate is not usable for signing\n"));
70   return GNUPG_Wrong_Key_Usage;
71 }
72
73
74 /* Return 0 if the cert is usable for signing */
75 int
76 gpgsm_cert_use_sign_p (KsbaCert cert)
77 {
78   return cert_usage_p (cert, 0);
79 }
80
81
82 /* Return 0 if the cert is usable for encryption */
83 int
84 gpgsm_cert_use_encrypt_p (KsbaCert cert)
85 {
86   return cert_usage_p (cert, 1);
87 }
88
89 int
90 gpgsm_cert_use_verify_p (KsbaCert cert)
91 {
92   return cert_usage_p (cert, 2);
93 }
94
95 int
96 gpgsm_cert_use_decrypt_p (KsbaCert cert)
97 {
98   return cert_usage_p (cert, 3);
99 }
100
101 /* add a certificate to a list of certificate and make sure that it is
102    a valid certificate */
103 int
104 gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
105 {
106   int rc;
107   KEYDB_SEARCH_DESC desc;
108   KEYDB_HANDLE kh = NULL;
109   KsbaCert cert = NULL;
110
111   rc = keydb_classify_name (name, &desc);
112   if (!rc)
113     {
114       kh = keydb_new (0);
115       if (!kh)
116         rc = GNUPG_Out_Of_Core;
117       else
118         {
119           int wrong_usage = 0;
120         get_next:
121           rc = keydb_search (kh, &desc, 1);
122           if (!rc)
123             rc = keydb_get_cert (kh, &cert);
124           if (!rc)
125             {
126               rc = gpgsm_cert_use_encrypt_p (cert);
127               if (rc == GNUPG_Wrong_Key_Usage)
128                 {
129                   /* There might be another certificate with the
130                      correct usage, so we better try again */
131                   wrong_usage = rc;
132                   ksba_cert_release (cert);
133                   cert = NULL;
134                   goto get_next;
135                 }
136             }
137           /* we want the error code from the first match in this case */
138           if (wrong_usage)
139             rc = wrong_usage;
140
141           if (!rc)
142             {
143               /* Fixme: If we ever have two certifciates differing
144                  only in the key usage, we should only bail out here
145                  if the certificate differes just in the key usage.
146                  However we need to find some criteria to match the
147                  identities */
148               rc = keydb_search (kh, &desc, 1);
149               if (rc == -1)
150                 rc = 0;
151               else if (!rc)
152                 rc = GNUPG_Ambiguous_Name;
153             }
154           if (!rc)
155             rc = gpgsm_validate_path (cert, NULL);
156           if (!rc)
157             {
158               CERTLIST cl = xtrycalloc (1, sizeof *cl);
159               if (!cl)
160                 rc = GNUPG_Out_Of_Core;
161               else 
162                 {
163                   cl->cert = cert; cert = NULL;
164                   cl->next = *listaddr;
165                   *listaddr = cl;
166                 }
167             }
168         }
169     }
170   
171   keydb_release (kh);
172   ksba_cert_release (cert);
173   return rc == -1? GNUPG_No_Public_Key: rc;
174 }
175
176 void
177 gpgsm_release_certlist (CERTLIST list)
178 {
179   while (list)
180     {
181       CERTLIST cl = list->next;
182       ksba_cert_release (list->cert);
183       xfree (list);
184       list = cl;
185     }
186 }
187
188 \f
189 /* Like gpgsm_add_to_certlist, but look only for one certificate.  No
190    path validation is done */
191 int
192 gpgsm_find_cert (const char *name, KsbaCert *r_cert)
193 {
194   int rc;
195   KEYDB_SEARCH_DESC desc;
196   KEYDB_HANDLE kh = NULL;
197
198   *r_cert = NULL;
199   rc = keydb_classify_name (name, &desc);
200   if (!rc)
201     {
202       kh = keydb_new (0);
203       if (!kh)
204         rc = GNUPG_Out_Of_Core;
205       else
206         {
207           rc = keydb_search (kh, &desc, 1);
208           if (!rc)
209             rc = keydb_get_cert (kh, r_cert);
210           if (!rc)
211             {
212               rc = keydb_search (kh, &desc, 1);
213               if (rc == -1)
214                 rc = 0;
215               else 
216                 {
217                   if (!rc)
218                     rc = GNUPG_Ambiguous_Name;
219                   ksba_cert_release (*r_cert);
220                   *r_cert = NULL;
221                 }
222             }
223         }
224     }
225   
226   keydb_release (kh);
227   return rc == -1? GNUPG_No_Public_Key: rc;
228 }
229