~ubuntu-branches/ubuntu/feisty/gnupg2/feisty

« back to all changes in this revision

Viewing changes to sm/certchain.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-07-11 11:38:13 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060711113813-zaw7unlbuh7gyxtl
Tags: 1.9.21-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* certchain.c - certificate chain validation
2
 
 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
2
 * Copyright (C) 2001, 2002, 2003, 2004, 2005,
 
3
 *               2006 Free Software Foundation, Inc.
3
4
 *
4
5
 * This file is part of GnuPG.
5
6
 *
15
16
 *
16
17
 * You should have received a copy of the GNU General Public License
17
18
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
20
 * USA.
19
21
 */
20
22
 
21
23
#include <config.h>
39
41
#include "i18n.h"
40
42
 
41
43
 
 
44
static int get_regtp_ca_info (ksba_cert_t cert, int *chainlen);
 
45
 
 
46
 
 
47
 
42
48
/* If LISTMODE is true, print FORMAT using LISTMODE to FP.  If
43
49
   LISTMODE is false, use the string to print an log_info or, if
44
50
   IS_ERROR is true, and log_error. */
128
134
    return err;
129
135
  if (!flag)
130
136
    {
 
137
      if (get_regtp_ca_info (cert, chainlen))
 
138
        {
 
139
          return 0; /* RegTP issued certificate. */
 
140
        }
 
141
 
131
142
      do_list (1, listmode, fp,_("issuer certificate is not marked as a CA"));
132
143
      return gpg_error (GPG_ERR_BAD_CA_CERT);
133
144
    }
267
278
}
268
279
 
269
280
 
270
 
/* Helper fucntion for find_up.  This resets the key handle and search
 
281
/* Helper function for find_up.  This resets the key handle and search
271
282
   for an issuer ISSUER with a subjectKeyIdentifier of KEYID.  Returns
272
283
   0 obn success or -1 when not found. */
273
284
static int
796
807
                {
797
808
                  /* Need to consult the list of root certificates for
798
809
                     qualified signatures. */
799
 
                  err = gpgsm_is_in_qualified_list (ctrl, subject_cert);
 
810
                  err = gpgsm_is_in_qualified_list (ctrl, subject_cert, NULL);
800
811
                  if (!err)
801
812
                    is_qualified = 1;
802
813
                  else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND)
807
818
                               gpg_strerror (err));
808
819
                  if ( is_qualified != -1 )
809
820
                    {
810
 
                      /* Cache the result but don't care toomuch about
811
 
                         an error. */
 
821
                      /* Cache the result but don't care too much
 
822
                         about an error. */
812
823
                      buf[0] = !!is_qualified;
813
824
                      err = ksba_cert_set_user_data (subject_cert,
814
825
                                                     "is_qualified", buf, 1);
1181
1192
  return rc;
1182
1193
}
1183
1194
 
 
1195
 
 
1196
 
 
1197
/* Check whether the certificate CERT has been issued by the German
 
1198
   authority for qualified signature.  They do not set the
 
1199
   basicConstraints and thus we need this workaround.  It works by
 
1200
   looking up the root certificate and checking whether that one is
 
1201
   listed as a qualified certificate for Germany. 
 
1202
 
 
1203
   We also try to cache this data but as long as don't keep a
 
1204
   reference to the certificate this won't be used.
 
1205
 
 
1206
   Returns: True if CERT is a RegTP issued CA cert (i.e. the root
 
1207
   certificate itself or one of the CAs).  In that case CHAINLEN will
 
1208
   receive the length of the chain which is either 0 or 1.
 
1209
*/
 
1210
static int
 
1211
get_regtp_ca_info (ksba_cert_t cert, int *chainlen)
 
1212
{
 
1213
  gpg_error_t err;
 
1214
  ksba_cert_t next;
 
1215
  int rc = 0;
 
1216
  int i, depth;
 
1217
  char country[3];
 
1218
  ksba_cert_t array[4];
 
1219
  char buf[2];
 
1220
  size_t buflen;
 
1221
  int dummy_chainlen;
 
1222
 
 
1223
  if (!chainlen)
 
1224
    chainlen = &dummy_chainlen;
 
1225
 
 
1226
  *chainlen = 0;
 
1227
  err = ksba_cert_get_user_data (cert, "regtp_ca_chainlen", 
 
1228
                                 &buf, sizeof (buf), &buflen);
 
1229
  if (!err)
 
1230
    {
 
1231
      /* Got info. */
 
1232
      if (buflen < 2 || !*buf)
 
1233
        return 0; /* Nothing found. */
 
1234
      *chainlen = buf[1];
 
1235
      return 1; /* This is a regtp CA. */
 
1236
    }
 
1237
  else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
 
1238
    {
 
1239
      log_error ("ksba_cert_get_user_data(%s) failed: %s\n",
 
1240
                 "regtp_ca_chainlen", gpg_strerror (err));
 
1241
      return 0; /* Nothing found.  */
 
1242
    }
 
1243
 
 
1244
  /* Need to gather the info.  This requires to walk up the chain
 
1245
     until we have found the root.  Because we are only interested in
 
1246
     German Bundesnetzagentur (former RegTP) derived certificates 3
 
1247
     levels are enough.  (The German signature law demands a 3 tier
 
1248
     hierachy; thus there is only one CA between the EE and the Root
 
1249
     CA.)  */
 
1250
  memset (&array, 0, sizeof array);
 
1251
 
 
1252
  depth = 0;
 
1253
  ksba_cert_ref (cert);
 
1254
  array[depth++] = cert;
 
1255
  ksba_cert_ref (cert);
 
1256
  while (depth < DIM(array) && !(rc=gpgsm_walk_cert_chain (cert, &next)))
 
1257
    {
 
1258
      ksba_cert_release (cert);
 
1259
      ksba_cert_ref (next);
 
1260
      array[depth++] = next;
 
1261
      cert = next;
 
1262
    }
 
1263
  ksba_cert_release (cert);
 
1264
  if (rc != -1 || !depth || depth == DIM(array) )
 
1265
    {
 
1266
      /* We did not reached the root. */
 
1267
      goto leave;
 
1268
    }
 
1269
 
 
1270
  /* If this is a German signature law issued certificate, we store
 
1271
     additional additional information. */
 
1272
  if (!gpgsm_is_in_qualified_list (NULL, array[depth-1], country)
 
1273
      && !strcmp (country, "de"))
 
1274
    {
 
1275
      /* Setting the pathlen for the root CA and the CA flag for the
 
1276
         next one is all what we need to do. */
 
1277
      err = ksba_cert_set_user_data (array[depth-1], "regtp_ca_chainlen",
 
1278
                                     "\x01\x01", 2);
 
1279
      if (!err && depth > 1)
 
1280
        err = ksba_cert_set_user_data (array[depth-2], "regtp_ca_chainlen",
 
1281
                                       "\x01\x00", 2);
 
1282
      if (err)
 
1283
        log_error ("ksba_set_user_data(%s) failed: %s\n",
 
1284
                   "regtp_ca_chainlen", gpg_strerror (err)); 
 
1285
      for (i=0; i < depth; i++)
 
1286
        ksba_cert_release (array[i]);
 
1287
      *chainlen = (depth>1? 0:1);
 
1288
      return 1;
 
1289
    }
 
1290
 
 
1291
 leave:
 
1292
  /* Nothing special with this certificate. Mark the target
 
1293
     certificate anyway to avoid duplicate lookups. */ 
 
1294
  err = ksba_cert_set_user_data (cert, "regtp_ca_chainlen", "", 1);
 
1295
  if (err)
 
1296
    log_error ("ksba_set_user_data(%s) failed: %s\n",
 
1297
               "regtp_ca_chainlen", gpg_strerror (err)); 
 
1298
  for (i=0; i < depth; i++)
 
1299
    ksba_cert_release (array[i]);
 
1300
  return 0;
 
1301
}