* keylist.c (list_internal_keys): Renamed from gpgsm_list_keys.
[gnupg.git] / sm / certchain.c
index ad408fd..28c0be5 100644 (file)
@@ -195,6 +195,33 @@ check_cert_policy (KsbaCert cert)
     }
 }
 
+
+static int
+find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
+{
+  KsbaName authid;
+  KsbaSexp authidno;
+  int rc = -1;
+
+  if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno))
+    {
+      const char *s = ksba_name_enum (authid, 0);
+      if (s && *authidno)
+        {
+          rc = keydb_search_issuer_sn (kh, s, authidno);
+          if (rc)
+              keydb_search_reset (kh);
+        }
+      ksba_name_release (authid);
+      xfree (authidno);
+    }
+  
+  if (rc)
+    rc = keydb_search_subject (kh, issuer);
+  return rc;
+}
+
+
 /* Return the next certificate up in the chain starting at START.
    Returns -1 when there are no more certificates. */
 int
@@ -233,8 +260,8 @@ gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next)
       rc = -1; /* we are at the root */
       goto leave; 
     }
-  rc = keydb_search_subject (kh, issuer);
+
+  rc = find_up (kh, start, issuer);
   if (rc)
     {
       /* it is quite common not to have a certificate, so better don't
@@ -278,23 +305,28 @@ gpgsm_is_root_cert (KsbaCert cert)
 }
 
 \f
+/* Validate a path and optionally return the nearest expiration time
+   in R_EXPTIME */
 int
-gpgsm_validate_path (KsbaCert cert)
+gpgsm_validate_path (KsbaCert cert, time_t *r_exptime)
 {
   int rc = 0, depth = 0, maxdepth;
   char *issuer = NULL;
   char *subject = NULL;
   KEYDB_HANDLE kh = keydb_new (0);
   KsbaCert subject_cert = NULL, issuer_cert = NULL;
-  time_t current_time = time (NULL);
+  time_t current_time = gnupg_get_time ();
+  time_t exptime = 0;
+
+  if (r_exptime)
+    *r_exptime = 0;
 
   if ((opt.debug & 4096))
     {
       log_info ("WARNING: bypassing path validation\n");
       return 0;
     }
-      
-
+  
   if (!kh)
     {
       log_error (_("failed to allocated keyDB handle\n"));
@@ -334,7 +366,15 @@ gpgsm_validate_path (KsbaCert cert)
             goto leave;
           }
 
-        if (current_time < not_before)
+        if (not_after)
+          {
+            if (!exptime)
+              exptime = not_after;
+            else if (not_after < exptime)
+              exptime = not_after;
+          }
+
+        if (not_before && current_time < not_before)
           {
             log_error ("certificate to young; valid from ");
             gpgsm_dump_time (not_before);
@@ -342,7 +382,7 @@ gpgsm_validate_path (KsbaCert cert)
             rc = GNUPG_Certificate_Too_Young;
             goto leave;
           }            
-        if (current_time > not_after)
+        if (not_after && current_time > not_after)
           {
             log_error ("certificate has expired at ");
             gpgsm_dump_time (not_after);
@@ -448,7 +488,7 @@ gpgsm_validate_path (KsbaCert cert)
 
       /* find the next cert up the tree */
       keydb_search_reset (kh);
-      rc = keydb_search_subject (kh, issuer);
+      rc = find_up (kh, subject_cert, issuer);
       if (rc)
         {
           if (rc == -1)
@@ -499,7 +539,8 @@ gpgsm_validate_path (KsbaCert cert)
           }
       }
 
-      log_info ("certificate is good\n");
+      if (opt.verbose)
+        log_info ("certificate is good\n");
       
       keydb_search_reset (kh);
       subject_cert = issuer_cert;
@@ -512,6 +553,8 @@ gpgsm_validate_path (KsbaCert cert)
     log_info ("CRLs not checked due to --disable-crl-checks option\n");
   
  leave:
+  if (r_exptime)
+    *r_exptime = exptime;
   xfree (issuer);
   keydb_release (kh); 
   ksba_cert_release (issuer_cert);
@@ -569,7 +612,7 @@ gpgsm_basic_cert_check (KsbaCert cert)
     {
       /* find the next cert up the tree */
       keydb_search_reset (kh);
-      rc = keydb_search_subject (kh, issuer);
+      rc = find_up (kh, cert, issuer);
       if (rc)
         {
           if (rc == -1)