1 /**
2  * Tool to generate an index file for the OpenSSL OCSP responder
3  *
4  * NOTE: This is a tool for setting up the test environment. At the
5  * moment, all certificates are marked as valid.
6  *
7  * Copyright 2016 Fiona Klute
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License"); you
10  * may not use this file except in compliance with the License.  You
11  * may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
18  * implied.  See the License for the specific language governing
19  * permissions and limitations under the License.
20  */
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <gnutls/gnutls.h>
26 #include <gnutls/x509.h>
27 
28 #include "cert_helper.h"
29 
30 
31 
index_line(const char * filename)32 static int index_line(const char* filename)
33 {
34     gnutls_datum_t rawcert;
35     /* read_cert reports errors to STDERR, just return if there were any */
36     if (read_cert(filename, &rawcert))
37         return GNUTLS_E_FILE_ERROR;
38 
39     gnutls_x509_crt_t cert;
40     gnutls_x509_crt_init(&cert);
41     int ret = gnutls_x509_crt_import(cert, &rawcert, GNUTLS_X509_FMT_PEM);
42     if (ret != GNUTLS_E_SUCCESS)
43         goto cleanup;
44 
45     /* For each certificate the index file contains a line with the
46      * tab separated fields declared below (in that order). */
47     /* status, one of: V (valid), R (revoked), E (expired) */
48     char* flag = "V";
49     /* expiration time (YYMMDDHHMMSSZ) */
50     char expires[14];
51     /* revocation time & optional reason (YYMMDDHHMMSSZ[,reason]), if
52      * any */
53     char* revocation = "";
54     /* serial number (hex), allocated when the length is known */
55     char* serial = NULL;
56     /* certificate filename, or "unknown" */
57     char* fname = "unknown";
58     /* certificate DN */
59     char dn[512];
60 
61     time_t etime = gnutls_x509_crt_get_expiration_time(cert);
62     struct tm etmp;
63     memset(&etmp, 0, sizeof(etmp));
64     gmtime_r(&etime, &etmp);
65     strftime(expires, sizeof(expires), "%y%m%d%H%M%SZ", &etmp);
66 
67     /* determine size of the serial number (in bytes) */
68     size_t serial_size = 0;
69     gnutls_x509_crt_get_serial(cert, NULL, &serial_size);
70     /* allocate memory for serial number and its string representation */
71     uint8_t* sno = calloc(serial_size, sizeof(uint8_t));
72     serial = calloc(serial_size * 2 + 1, sizeof(char));
73     /* actually get the serial */
74     gnutls_x509_crt_get_serial(cert, sno, &serial_size);
75     /* print serial into the buffer byte for byte */
76     for (int i = 0; i < serial_size; i++)
77         snprintf(serial + (2 * i), 3, "%.2X", sno[i]);
78     /* free binary serial */
79     free(sno);
80 
81     size_t dn_size = sizeof(dn);
82     gnutls_x509_crt_get_dn(cert, dn, &dn_size);
83 
84     fprintf(stdout, "%s\t%s\t%s\t%s\t%s\t%s\n",
85             flag, expires, revocation, serial, fname, dn);
86 
87     /* free hex serial */
88     free(serial);
89 
90 cleanup:
91     gnutls_x509_crt_deinit(cert);
92     free(rawcert.data);
93     return ret;
94 }
95 
96 
97 
main(int argc,char * argv[])98 int main(int argc, char *argv[])
99 {
100     if (argc < 2)
101     {
102         fprintf(stderr, "Usage:\t%s CERTIFICATE ...\n", argv[0]);
103         return 1;
104     }
105 
106     int ret = 0;
107     for (int i = 1; i < argc; i++)
108     {
109         int rv = index_line(argv[i]);
110         if (rv != GNUTLS_E_SUCCESS)
111         {
112             fprintf(stderr, "Error parsing %s: %s\n",
113                     argv[i], gnutls_strerror(rv));
114             ret = 1;
115         }
116     }
117     return ret;
118 }
119