Added support for delta CRLs to pki tool
authorMartin Willi <martin@revosec.ch>
Fri, 17 Dec 2010 16:00:32 +0000 (17:00 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:46:04 +0000 (16:46 +0100)
src/pki/commands/issue.c
src/pki/commands/print.c
src/pki/commands/signcrl.c

index 2c0f1e0..2ebb565 100644 (file)
@@ -244,7 +244,7 @@ static int issue()
                                continue;
                        case 'u':
                                INIT(cdp,
-                                       .uri = strdup(arg),
+                                       .uri = arg,
                                );
                                cdps->insert_last(cdps, cdp);
                                continue;
index f0795ea..185895e 100644 (file)
@@ -318,14 +318,41 @@ static void print_crl(crl_t *crl)
        crl_reason_t reason;
        chunk_t chunk;
        int count = 0;
+       bool first;
        char buf[64];
        struct tm tm;
+       x509_cdp_t *cdp;
 
        chunk = crl->get_serial(crl);
        printf("serial:    %#B\n", &chunk);
+       if (crl->is_delta_crl(crl, &chunk))
+       {
+               printf("delta CRL: for serial %#B\n", &chunk);
+       }
        chunk = crl->get_authKeyIdentifier(crl);
        printf("authKeyId: %#B\n", &chunk);
 
+       first = TRUE;
+       enumerator = crl->create_delta_crl_uri_enumerator(crl);
+       while (enumerator->enumerate(enumerator, &cdp))
+       {
+               if (first)
+               {
+                       printf("freshest:  %s", cdp->uri);
+                       first = FALSE;
+               }
+               else
+               {
+                       printf("           %s", cdp->uri);
+               }
+               if (cdp->issuer)
+               {
+                       printf(" (CRL issuer: %Y)", cdp->issuer);
+               }
+               printf("\n");
+       }
+       enumerator->destroy(enumerator);
+
        enumerator = crl->create_enumerator(crl);
        while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
        {
index 87d5853..07f4a13 100644 (file)
@@ -98,6 +98,15 @@ static int read_serial(char *file, char *buf, int buflen)
 }
 
 /**
+ * Destroy a CDP
+ */
+static void cdp_destroy(x509_cdp_t *this)
+{
+       free(this->uri);
+       free(this);
+}
+
+/**
  * Sign a CRL
  */
 static int sign_crl()
@@ -110,16 +119,19 @@ static int sign_crl()
        x509_t *x509;
        hash_algorithm_t digest = HASH_SHA1;
        char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL;
+       char *basecrl = NULL;
        char serial[512], crl_serial[8], *keyid = NULL;
        int serial_len = 0;
        crl_reason_t reason = CRL_REASON_UNSPECIFIED;
        time_t thisUpdate, nextUpdate, date = time(NULL);
        int lifetime = 15;
-       linked_list_t *list;
+       linked_list_t *list, *cdps;
        enumerator_t *enumerator, *lastenum = NULL;
-       chunk_t encoding = chunk_empty;
+       x509_cdp_t *cdp;
+       chunk_t encoding = chunk_empty, baseCrlNumber = chunk_empty;
 
        list = linked_list_create();
+       cdps = linked_list_create();
 
        memset(crl_serial, 0, sizeof(crl_serial));
 
@@ -190,6 +202,15 @@ static int sign_crl()
                                reason = CRL_REASON_UNSPECIFIED;
                                continue;
                        }
+                       case 'b':
+                               basecrl = arg;
+                               continue;
+                       case 'u':
+                               INIT(cdp,
+                                       .uri = strdup(arg),
+                               );
+                               cdps->insert_last(cdps, cdp);
+                               continue;
                        case 'r':
                                if (streq(arg, "key-compromise"))
                                {
@@ -302,6 +323,20 @@ static int sign_crl()
        thisUpdate = time(NULL);
        nextUpdate = thisUpdate + lifetime * 24 * 60 * 60;
 
+       if (basecrl)
+       {
+               lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+                                                                        BUILD_FROM_FILE, basecrl, BUILD_END);
+               if (!lastcrl)
+               {
+                       error = "loading base CRL failed";
+                       goto error;
+               }
+               baseCrlNumber = chunk_clone(lastcrl->get_serial(lastcrl));
+               DESTROY_IF((certificate_t*)lastcrl);
+               lastcrl = NULL;
+       }
+
        if (lastupdate)
        {
                lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
@@ -315,6 +350,10 @@ static int sign_crl()
                           min(lastcrl->get_serial(lastcrl).len, sizeof(crl_serial)));
                lastenum = lastcrl->create_enumerator(lastcrl);
        }
+       else
+       {
+               lastenum = enumerator_create_empty();
+       }
 
        chunk_increment(chunk_create(crl_serial, sizeof(crl_serial)));
 
@@ -324,11 +363,12 @@ static int sign_crl()
                        BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca,
                        BUILD_SERIAL, chunk_create(crl_serial, sizeof(crl_serial)),
                        BUILD_NOT_BEFORE_TIME, thisUpdate, BUILD_NOT_AFTER_TIME, nextUpdate,
-                       BUILD_REVOKED_ENUMERATOR, enumerator, BUILD_DIGEST_ALG, digest,
-                       lastenum ? BUILD_REVOKED_ENUMERATOR : BUILD_END, lastenum,
+                       BUILD_REVOKED_ENUMERATOR, enumerator,
+                       BUILD_REVOKED_ENUMERATOR, lastenum, BUILD_DIGEST_ALG, digest,
+                       BUILD_CRL_DISTRIBUTION_POINTS, cdps, BUILD_BASE_CRL, baseCrlNumber,
                        BUILD_END);
        enumerator->destroy(enumerator);
-       DESTROY_IF(lastenum);
+       lastenum->destroy(lastenum);
        DESTROY_IF((certificate_t*)lastcrl);
 
        if (!crl)
@@ -353,7 +393,9 @@ error:
        DESTROY_IF(ca);
        DESTROY_IF(crl);
        free(encoding.ptr);
+       free(baseCrlNumber.ptr);
        list->destroy_function(list, (void*)revoked_destroy);
+       cdps->destroy_function(cdps, (void*)cdp_destroy);
        if (error)
        {
                fprintf(stderr, "%s\n", error);
@@ -363,6 +405,7 @@ error:
 
 usage:
        list->destroy_function(list, (void*)revoked_destroy);
+       cdps->destroy_function(cdps, (void*)cdp_destroy);
        return command_usage(error);
 }
 
@@ -375,24 +418,27 @@ static void __attribute__ ((constructor))reg()
                sign_crl, 'c', "signcrl",
                "issue a CRL using a CA certificate and key",
                {"--cacert file --cakey file | --cakeyid hex --lifetime days",
+                "[--lastcrl crl] [--basecrl crl] [--crluri uri ]+",
                 "[  [--reason key-compromise|ca-compromise|affiliation-changed|",
                 "             superseded|cessation-of-operation|certificate-hold]",
                 "   [--date timestamp]",
                 "    --cert file | --serial hex ]*",
                 "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"},
                {
-                       {"help",        'h', 0, "show usage information"},
-                       {"cacert",      'c', 1, "CA certificate file"},
-                       {"cakey",       'k', 1, "CA private key file"},
-                       {"cakeyid",     'x', 1, "keyid on smartcard of CA private key"},
-                       {"lifetime",'l', 1, "days the CRL gets a nextUpdate, default: 15"},
-                       {"lastcrl",     'a', 1, "CRL of lastUpdate to copy revocations from"},
-                       {"cert",        'z', 1, "certificate file to revoke"},
-                       {"serial",      's', 1, "hex encoded certificate serial number to revoke"},
-                       {"reason",      'r', 1, "reason for certificate revocation"},
-                       {"date",        'd', 1, "revocation date as unix timestamp, default: now"},
-                       {"digest",      'g', 1, "digest for signature creation, default: sha1"},
-                       {"outform",     'f', 1, "encoding of generated crl, default: der"},
+                       {"help",                'h', 0, "show usage information"},
+                       {"cacert",              'c', 1, "CA certificate file"},
+                       {"cakey",               'k', 1, "CA private key file"},
+                       {"cakeyid",             'x', 1, "keyid on smartcard of CA private key"},
+                       {"lifetime",    'l', 1, "days the CRL gets a nextUpdate, default: 15"},
+                       {"lastcrl",             'a', 1, "CRL of lastUpdate to copy revocations from"},
+                       {"basecrl",             'b', 1, "base CRL to create a delta CRL for"},
+                       {"crluri",              'u', 1, "freshest delta CRL URI to include"},
+                       {"cert",                'z', 1, "certificate file to revoke"},
+                       {"serial",              's', 1, "hex encoded certificate serial number to revoke"},
+                       {"reason",              'r', 1, "reason for certificate revocation"},
+                       {"date",                'd', 1, "revocation date as unix timestamp, default: now"},
+                       {"digest",              'g', 1, "digest for signature creation, default: sha1"},
+                       {"outform",             'f', 1, "encoding of generated crl, default: der"},
                }
        });
 }